using System; using System.Linq; using System.Reflection; using System.Linq.Expressions; namespace GraphicsCat { public static class ReflectionUtils { #region Method Invocation (supports private methods) /// /// Invoke instance method (supports private methods) /// public static object InvokeMethod(T instance, string methodName, object[] parameters = null) { if (instance == null) throw new ArgumentNullException(nameof(instance)); var methodInfo = GetMethodInfo(methodName, parameters); return methodInfo.Invoke(instance, parameters ?? Array.Empty()); } /// /// Invoke static method (supports private methods) /// public static object InvokeStaticMethod(string methodName, object[] parameters = null) { var methodInfo = GetMethodInfo(methodName, parameters, isStatic: true); return methodInfo.Invoke(null, parameters ?? Array.Empty()); } /// /// Invoke generic instance method (supports private methods) /// public static object InvokeGenericMethod(T instance, string methodName, Type[] genericTypes, object[] parameters = null) { if (instance == null) throw new ArgumentNullException(nameof(instance)); var methodInfo = GetMethodInfo(methodName, parameters).MakeGenericMethod(genericTypes); return methodInfo.Invoke(instance, parameters ?? Array.Empty()); } private static MethodInfo GetMethodInfo(string methodName, object[] parameters, bool isStatic = false) { var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic; bindingFlags |= isStatic ? BindingFlags.Static : BindingFlags.Instance; var type = typeof(T); if (parameters == null || parameters.Length == 0) { var methodInfo = type.GetMethod(methodName, bindingFlags); if (methodInfo == null) throw new MissingMethodException($"Method '{methodName}' not found in type '{type.FullName}'"); return methodInfo; } var parameterTypes = parameters.Select(p => p?.GetType()).ToArray(); var method = type.GetMethod(methodName, bindingFlags, null, parameterTypes, null); if (method == null) throw new MissingMethodException($"Method '{methodName}' not found in type '{type.FullName}' with specified parameters"); return method; } #endregion #region Property Access (supports private properties) /// /// Get instance property value (supports private properties) /// public static object GetPropertyValue(T instance, string propertyName) { if (instance == null) throw new ArgumentNullException(nameof(instance)); var propertyInfo = GetPropertyInfo(propertyName); return propertyInfo.GetValue(instance); } /// /// Set instance property value (supports private properties) /// public static void SetPropertyValue(T instance, string propertyName, object value) { if (instance == null) throw new ArgumentNullException(nameof(instance)); var propertyInfo = GetPropertyInfo(propertyName); propertyInfo.SetValue(instance, value); } /// /// Get static property value (supports private properties) /// public static object GetStaticPropertyValue(string propertyName) { var propertyInfo = GetPropertyInfo(propertyName, isStatic: true); return propertyInfo.GetValue(null); } /// /// Set static property value (supports private properties) /// public static void SetStaticPropertyValue(string propertyName, object value) { var propertyInfo = GetPropertyInfo(propertyName, isStatic: true); propertyInfo.SetValue(null, value); } private static PropertyInfo GetPropertyInfo(string propertyName, bool isStatic = false) { var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic; bindingFlags |= isStatic ? BindingFlags.Static : BindingFlags.Instance; var type = typeof(T); var propertyInfo = type.GetProperty(propertyName, bindingFlags); if (propertyInfo == null) throw new MissingMemberException($"Property '{propertyName}' not found in type '{type.FullName}'"); return propertyInfo; } #endregion #region Field Access (supports private fields) /// /// Get instance field value (supports private fields) /// public static object GetFieldValue(T instance, string fieldName) { if (instance == null) throw new ArgumentNullException(nameof(instance)); var fieldInfo = GetFieldInfo(fieldName); return fieldInfo.GetValue(instance); } /// /// Set instance field value (supports private fields) /// public static void SetFieldValue(T instance, string fieldName, object value) { if (instance == null) throw new ArgumentNullException(nameof(instance)); var fieldInfo = GetFieldInfo(fieldName); fieldInfo.SetValue(instance, value); } /// /// Get static field value (supports private fields) /// public static object GetStaticFieldValue(string fieldName) { var fieldInfo = GetFieldInfo(fieldName, isStatic: true); return fieldInfo.GetValue(null); } /// /// Set static field value (supports private fields) /// public static void SetStaticFieldValue(string fieldName, object value) { var fieldInfo = GetFieldInfo(fieldName, isStatic: true); fieldInfo.SetValue(null, value); } private static FieldInfo GetFieldInfo(string fieldName, bool isStatic = false) { var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic; bindingFlags |= isStatic ? BindingFlags.Static : BindingFlags.Instance; var type = typeof(T); var fieldInfo = type.GetField(fieldName, bindingFlags); if (fieldInfo == null) throw new MissingMemberException($"Field '{fieldName}' not found in type '{type.FullName}'"); return fieldInfo; } #endregion #region Instance Creation (supports private constructors) /// /// Create instance (supports private constructors) /// public static T CreateInstance(object[] parameters = null) { return (T)CreateInstance(typeof(T), parameters); } private static object CreateInstance(Type type, object[] parameters) { const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; if (parameters == null || parameters.Length == 0) { var ctor = type.GetConstructor(bindingFlags, null, Type.EmptyTypes, null); if (ctor == null) throw new MissingMethodException($"Parameterless constructor not found in type '{type.FullName}'"); return ctor.Invoke(Array.Empty()); } var parameterTypes = parameters.Select(p => p?.GetType()).ToArray(); var constructor = type.GetConstructor(bindingFlags, null, parameterTypes, null); if (constructor == null) throw new MissingMethodException($"Constructor not found in type '{type.FullName}' with specified parameters"); return constructor.Invoke(parameters); } #endregion #region Extension Methods (based on expressions) /// /// Invoke instance method through expression /// public static object InvokeMethod(T instance, Expression> expression) { if (expression.Body is MethodCallExpression methodCall) { var methodInfo = methodCall.Method; var parameters = methodCall.Arguments.Select(GetExpressionValue).ToArray(); return methodInfo.Invoke(instance, parameters); } throw new ArgumentException("Expression is not a method call", nameof(expression)); } /// /// Get property value through expression /// public static TProp GetPropertyValue(T instance, Expression> expression) { if (expression.Body is MemberExpression memberExpression && memberExpression.Member is PropertyInfo propertyInfo) { return (TProp)propertyInfo.GetValue(instance); } throw new ArgumentException("Expression is not a property access", nameof(expression)); } /// /// Get field value through expression /// public static TField GetFieldValue(T instance, Expression> expression) { if (expression.Body is MemberExpression memberExpression && memberExpression.Member is FieldInfo fieldInfo) { return (TField)fieldInfo.GetValue(instance); } throw new ArgumentException("Expression is not a field access", nameof(expression)); } private static object GetExpressionValue(Expression expression) { if (expression is ConstantExpression constantExpression) return constantExpression.Value; var lambda = Expression.Lambda(expression); return lambda.Compile().DynamicInvoke(); } #endregion } }