// MIT License - Copyright (c) 2025 wallstop // Full license text: https://github.com/wallstop/unity-helpers/blob/main/LICENSE #if !((UNITY_WEBGL && !UNITY_EDITOR) || ENABLE_IL2CPP) #define EMIT_DYNAMIC_IL #define SUPPORT_EXPRESSION_COMPILE #endif namespace WallstopStudios.UnityHelpers.Core.Helper { using System; using System.Collections; using System.Collections.Generic; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using WallstopStudios.UnityHelpers.Utils; #if UNITY_EDITOR #endif #if EMIT_DYNAMIC_IL using System.Reflection.Emit; #endif #if !SINGLE_THREADED using System.Collections.Concurrent; #else using Extension; #endif public delegate void FieldSetter(ref TInstance instance, TValue value); /// /// High-performance reflection helpers for field/property access, method/constructor invocation, /// dynamic collection creation, and type/attribute scanning with caching and optional IL emission. /// /// /// Architecture Overview /// /// This class provides a unified API for reflection-based operations while automatically selecting /// the highest-performance implementation strategy available on the current platform. The implementation /// uses a three-tier fallback system: /// /// /// /// Expression Trees (preferred) /// /// Uses System.Linq.Expressions to build and compile lambda expressions at runtime. /// This produces near-native performance delegates. Available on Mono and .NET runtimes that /// support JIT compilation. Disabled on IL2CPP and WebGL builds where AOT compilation is required. /// /// /// /// Dynamic IL Emission (fallback #1) /// /// Uses System.Reflection.Emit.DynamicMethod to generate IL bytecode directly. /// Provides similar performance to expression trees but with more control over the generated code. /// Also disabled on IL2CPP and WebGL. Some edge cases that fail expression compilation may /// succeed with IL emission. /// /// /// /// Direct Reflection (fallback #2) /// /// Falls back to standard FieldInfo.GetValue/SetValue, PropertyInfo, /// MethodInfo.Invoke, and ConstructorInfo.Invoke calls. This is the slowest /// option but works on all platforms including IL2CPP and WebGL. /// /// /// /// Platform Support /// /// /// Platform /// Strategy Used /// /// /// Unity Editor /// Expression Trees → Dynamic IL → Reflection /// /// /// Standalone (Mono) /// Expression Trees → Dynamic IL → Reflection /// /// /// IL2CPP Builds /// Reflection only (JIT unavailable) /// /// /// WebGL /// Reflection only (JIT unavailable) /// /// /// Caching Strategy /// /// All generated delegates are cached using thread-safe concurrent dictionaries (or regular dictionaries /// when SINGLE_THREADED is defined). The cache key includes both the member info and the strategy /// used, allowing the system to track which strategies have been attempted and failed for each member. /// A blocklist tracks strategies that failed for specific members, avoiding repeated failed attempts. /// /// Testing Support /// /// The internal OverrideReflectionCapabilities method allows tests to force specific strategies, /// enabling verification that all fallback paths work correctly. Use the returned IDisposable /// to restore original capabilities after the test. /// /// File Organization /// /// This is a partial class split across multiple files: /// /// /// ReflectionHelpers.cs - Public API, caching infrastructure, IL emission methods /// ReflectionHelpers.Factory.cs - Internal DelegateFactory class managing /// delegate creation, strategy selection, and caching for each member type /// /// /// /// object /// var setter = ReflectionHelpers.GetFieldSetter(field); // (object, object) -> void /// var p = new Player(); /// setter(p, 42); /// UnityEngine.Debug.Log(getter(p)); // 42 /// ]]> /// /// /// All public methods are thread-safe. Internal caching uses ConcurrentDictionary by default, /// or standard dictionaries with external synchronization when SINGLE_THREADED is defined. /// public static partial class ReflectionHelpers { /// /// The standard property name for Unity's Behaviour.enabled property. /// private const string EnabledPropertyName = "enabled"; // Cache for type resolution by name #if !SINGLE_THREADED private static readonly ConcurrentDictionary TypeResolutionCache = new( StringComparer.Ordinal ); #else private static readonly Dictionary TypeResolutionCache = new( StringComparer.Ordinal ); #endif #if SINGLE_THREADED private static readonly Dictionary> ArrayCreators = new(); private static readonly Dictionary> ListCreators = new(); private static readonly Dictionary> ListWithCapacityCreators = new(); private static readonly Dictionary> HashSetWithCapacityCreators = new(); private static readonly Dictionary> HashSetClearers = new(); [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Func GetArrayCreatorCached(Type type) { if (!ArrayCreators.TryGetValue(type, out Func factory)) { factory = GetArrayCreator(type); ArrayCreators[type] = factory; } return factory; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Func GetListWithCapacityCreatorCached(Type elementType) { if (!ListWithCapacityCreators.TryGetValue(elementType, out Func factory)) { factory = GetListWithCapacityCreator(elementType); ListWithCapacityCreators[elementType] = factory; } return factory; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Func GetListCreatorCached(Type elementType) { if (!ListCreators.TryGetValue(elementType, out Func factory)) { factory = GetListCreator(elementType); ListCreators[elementType] = factory; } return factory; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Func GetHashSetWithCapacityCreatorCached(Type elementType) { if ( !HashSetWithCapacityCreators.TryGetValue(elementType, out Func factory) ) { factory = GetHashSetWithCapacityCreator(elementType); HashSetWithCapacityCreators[elementType] = factory; } return factory; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Action GetHashSetClearerCached(Type elementType) { if (!HashSetClearers.TryGetValue(elementType, out Action clearer)) { clearer = GetHashSetClearer(elementType); HashSetClearers[elementType] = clearer; } return clearer; } #else private static readonly ConcurrentDictionary> ArrayCreators = new(); private static readonly ConcurrentDictionary> ListCreators = new(); private static readonly ConcurrentDictionary< Type, Func > ListWithCapacityCreators = new(); private static readonly ConcurrentDictionary< Type, Func > HashSetWithCapacityCreators = new(); private static readonly ConcurrentDictionary> HashSetClearers = new(); [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Func GetArrayCreatorCached(Type type) { return ArrayCreators.GetOrAdd(type, static elementType => GetArrayCreator(elementType)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Func GetListWithCapacityCreatorCached(Type elementType) { return ListWithCapacityCreators.GetOrAdd( elementType, static type => GetListWithCapacityCreator(type) ); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Func GetListCreatorCached(Type elementType) { return ListCreators.GetOrAdd(elementType, static type => GetListCreator(type)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Func GetHashSetWithCapacityCreatorCached(Type elementType) { return HashSetWithCapacityCreators.GetOrAdd( elementType, static type => GetHashSetWithCapacityCreator(type) ); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Action GetHashSetClearerCached(Type elementType) { return HashSetClearers.GetOrAdd(elementType, static type => GetHashSetClearer(type)); } #endif private static readonly bool CanCompileExpressions = CheckExpressionCompilationSupport(); private static readonly bool DynamicIlSupported = CheckDynamicIlSupport(); private static bool? _expressionCapabilityOverride; private static bool? _dynamicIlCapabilityOverride; internal static bool ExpressionsEnabled => _expressionCapabilityOverride ?? CanCompileExpressions; internal static bool DynamicIlEnabled => _dynamicIlCapabilityOverride ?? DynamicIlSupported; internal static IDisposable OverrideReflectionCapabilities( bool? expressions, bool? dynamicIl ) { bool? previousExpressions = _expressionCapabilityOverride; bool? previousDynamicIl = _dynamicIlCapabilityOverride; _expressionCapabilityOverride = expressions; _dynamicIlCapabilityOverride = dynamicIl; return new CapabilityOverrideScope(previousExpressions, previousDynamicIl); } private sealed class CapabilityOverrideScope : IDisposable { private readonly bool? _previousExpressions; private readonly bool? _previousDynamicIl; private bool _disposed; internal CapabilityOverrideScope(bool? expressions, bool? dynamicIl) { _previousExpressions = expressions; _previousDynamicIl = dynamicIl; } public void Dispose() { if (_disposed) { return; } _expressionCapabilityOverride = _previousExpressions; _dynamicIlCapabilityOverride = _previousDynamicIl; _disposed = true; } } #if SINGLE_THREADED private static readonly Dictionary< (Type type, string name, BindingFlags flags), FieldInfo > FieldLookup = new(); private static readonly Dictionary< (Type type, string name, BindingFlags flags), PropertyInfo > PropertyLookup = new(); private static readonly Dictionary< (Type type, string sig, BindingFlags flags), MethodInfo > MethodLookup = new(); private static readonly Dictionary< (Type type, BindingFlags flags), FieldInfo[] > FieldArrayCache = new(); private static readonly Dictionary< (Type type, Type returnType, string indexParamsSig), PropertyInfo > IndexerLookup = new(); #else private static readonly ConcurrentDictionary< (Type type, string name, BindingFlags flags), FieldInfo > FieldLookup = new(); private static readonly ConcurrentDictionary< (Type type, string name, BindingFlags flags), PropertyInfo > PropertyLookup = new(); private static readonly ConcurrentDictionary< (Type type, string sig, BindingFlags flags), MethodInfo > MethodLookup = new(); private static readonly ConcurrentDictionary< (Type type, BindingFlags flags), FieldInfo[] > FieldArrayCache = new(); private static readonly ConcurrentDictionary< (Type type, Type returnType, string indexParamsSig), PropertyInfo > IndexerLookup = new(); #endif private const BindingFlags AllInstanceFieldsFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static; /// /// Gets all fields for a type with caching to avoid repeated allocations. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static FieldInfo[] GetFieldsCached(Type type, BindingFlags flags) { if (type == null) { return Array.Empty(); } (Type, BindingFlags) key = (type, flags); #if SINGLE_THREADED if (!FieldArrayCache.TryGetValue(key, out FieldInfo[] fields)) { try { fields = type.GetFields(flags); } catch { fields = Array.Empty(); } FieldArrayCache[key] = fields; } return fields; #else return FieldArrayCache.GetOrAdd( key, static k => { try { return k.type.GetFields(k.flags); } catch { return Array.Empty(); } } ); #endif } /// /// Tries to get an attribute of type and indicates whether it is present. /// Safe: returns false on any reflection errors. /// /// Any member, type, or assembly supporting attributes. /// Output attribute instance if found, otherwise default. /// Whether to search base types. /// True if attribute exists; otherwise false. /// /// /// public static bool IsAttributeDefined( this ICustomAttributeProvider provider, out T attribute, bool inherit = true ) where T : Attribute { try { Type type = typeof(T); if (provider.IsDefined(type, inherit)) { object[] attributes = provider.GetCustomAttributes(type, inherit); if (attributes.Length == 0) { attribute = default; return false; } attribute = Unsafe.As(attributes[0]); return attribute != null; } } catch { // Swallow } attribute = default; return false; } /// /// Loads all public static properties whose property type is exactly , /// keyed by property name (case-insensitive). /// /// /// Use when enumerating well-known static instances or singletons of a type. /// /// /// (); /// foreach (var kvp in props) UnityEngine.Debug.Log($"{kvp.Key} -> {kvp.Value}"); /// ]]> /// public static Dictionary LoadStaticPropertiesForType() { Type type = typeof(T); PropertyInfo[] properties = type.GetProperties( BindingFlags.Static | BindingFlags.Public ); Dictionary result = new( properties.Length, StringComparer.OrdinalIgnoreCase ); for (int i = 0; i < properties.Length; i++) { PropertyInfo property = properties[i]; if (property.PropertyType == type) { result[property.Name] = property; } } return result; } /// /// Loads all public static fields whose field type is exactly , /// keyed by field name (case-insensitive). /// /// /// Use when mapping constant instances or static registries. /// /// /// (); /// // Access FieldInfo directly to get or set values /// ]]> /// public static Dictionary LoadStaticFieldsForType() { Type type = typeof(T); FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public); Dictionary result = new( fields.Length, StringComparer.OrdinalIgnoreCase ); for (int i = 0; i < fields.Length; i++) { FieldInfo field = fields[i]; if (field.FieldType == type) { result[field.Name] = field; } } return result; } /// /// Creates a new array instance of element with the specified length. /// /// /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Array CreateArray(Type type, int length) { return GetArrayCreatorCached(type).Invoke(length); } /// /// Creates a new instance for with the specified capacity. /// /// /// with Capacity=128 /// ]]> /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IList CreateList(Type elementType, int length) { return GetListWithCapacityCreatorCached(elementType).Invoke(length); } /// /// Creates a new instance for . /// /// /// /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IList CreateList(Type elementType) { return GetListCreatorCached(elementType).Invoke(); } // Test helpers to avoid reflection in tests when asserting cache state internal static bool IsFieldGetterCached(FieldInfo field) { return DelegateFactory.IsFieldGetterCached(field); } internal static bool IsFieldSetterCached(FieldInfo field) { return DelegateFactory.IsFieldSetterCached(field); } internal static void ClearFieldGetterCache() { DelegateFactory.ClearFieldGetterCache(); } internal static void ClearFieldSetterCache() { DelegateFactory.ClearFieldSetterCache(); } internal static void ClearPropertyCache() { DelegateFactory.ClearPropertyCache(); } internal static void ClearMethodCache() { DelegateFactory.ClearMethodCache(); } internal static void ClearConstructorCache() { DelegateFactory.ClearConstructorCache(); } internal static bool TryGetDelegateStrategy( Delegate delegateInstance, out ReflectionDelegateStrategy strategy ) { return DelegateFactory.TryGetStrategy(delegateInstance, out strategy); } /// /// Builds a cached delegate that returns the value of a field as . /// Supports instance and static fields. /// /// Field to read. /// Delegate: object instance => object value /// /// /// public static Func GetFieldGetter(FieldInfo field) { return DelegateFactory.GetFieldGetter(field); } #if EMIT_DYNAMIC_IL private static Func BuildFieldGetterIL(FieldInfo field) { DynamicMethod dynamicMethod = new( $"Get{field.DeclaringType.Name}_{field.Name}", typeof(object), new[] { typeof(object) }, field.DeclaringType, true ); ILGenerator il = dynamicMethod.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit( field.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, field.DeclaringType ); il.Emit(OpCodes.Ldfld, field); if (field.FieldType.IsValueType) { il.Emit(OpCodes.Box, field.FieldType); } il.Emit(OpCodes.Ret); return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } #endif /// /// Builds a cached delegate that returns the value of a property as . /// Supports static and instance properties. /// /// Property to read. /// Delegate: object instanceOrNull => object value /// /// /// public static Func GetPropertyGetter(PropertyInfo property) { return DelegateFactory.GetPropertyGetter(property); } #if EMIT_DYNAMIC_IL private static Func BuildPropertyGetterIL(PropertyInfo property) { MethodInfo getMethod = property.GetGetMethod(true); DynamicMethod dynamicMethod = new( $"Get{property.DeclaringType.Name}_{property.Name}", typeof(object), new[] { typeof(object) }, property.DeclaringType, true ); ILGenerator il = dynamicMethod.GetILGenerator(); if (getMethod.IsStatic) { il.Emit(OpCodes.Call, getMethod); } else { il.Emit(OpCodes.Ldarg_0); il.Emit( property.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, property.DeclaringType ); il.Emit( property.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt, getMethod ); } if (property.PropertyType.IsValueType) { il.Emit(OpCodes.Box, property.PropertyType); } il.Emit(OpCodes.Ret); return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } #endif /// /// Builds a strongly-typed property getter delegate. /// Supports static and instance properties; for static, the instance argument is ignored. /// /// Declaring type or compatible type. /// Expected property value type. /// Property to read. /// Delegate: TInstance instance => TValue value /// /// (pi); /// var obj = new TestPropertyClass { InstanceProperty = 123 }; /// int value = getter(obj); // 123 /// ]]> /// public static Func GetPropertyGetter( PropertyInfo property ) { return DelegateFactory.GetPropertyGetterTyped(property); } /// /// Builds a boxed setter delegate for a property. /// Supports instance and static properties. Throws if property has no setter. /// /// Property to set. /// Delegate: (object instanceOrNull, object value) => void /// /// /// public static Action GetPropertySetter(PropertyInfo property) { MethodInfo setMethod = property.GetSetMethod(true); if (setMethod == null) { throw new ArgumentException( $"Property {property?.Name} has no setter", nameof(property) ); } return DelegateFactory.GetPropertySetter(property); } public static Action GetPropertySetter( PropertyInfo property ) { MethodInfo setMethod = property.GetSetMethod(true); if (setMethod == null) { throw new ArgumentException( $"Property {property?.Name} has no setter", nameof(property) ); } return DelegateFactory.GetPropertySetterTyped(property); } public static Action GetStaticPropertySetter(PropertyInfo property) { MethodInfo setMethod = property.GetSetMethod(true); if (setMethod == null || !setMethod.IsStatic) { throw new ArgumentException( $"Property {property?.Name} must be static and have a setter", nameof(property) ); } return DelegateFactory.GetStaticPropertySetterTyped(property); } public static Func GetIndexerGetter(PropertyInfo property) { if (property == null) { throw new ArgumentNullException(nameof(property)); } ParameterInfo[] indices = property.GetIndexParameters(); if (indices == null || indices.Length == 0) { throw new ArgumentException("Property is not an indexer", nameof(property)); } MethodInfo getter = property.GetGetMethod(true); if (getter == null) { throw new ArgumentException("Indexer has no getter", nameof(property)); } return DelegateFactory.GetIndexerGetter(property); } public static Action GetIndexerSetter(PropertyInfo property) { if (property == null) { throw new ArgumentNullException(nameof(property)); } ParameterInfo[] indices = property.GetIndexParameters(); if (indices == null || indices.Length == 0) { throw new ArgumentException("Property is not an indexer", nameof(property)); } MethodInfo setter = property.GetSetMethod(true); if (setter == null) { throw new ArgumentException("Indexer has no setter", nameof(property)); } return DelegateFactory.GetIndexerSetter(property); } #if EMIT_DYNAMIC_IL private static Action BuildPropertySetterIL(PropertyInfo property) { MethodInfo setMethod = property.GetSetMethod(true); DynamicMethod dynamicMethod = new( $"SetProperty{property.DeclaringType.Name}_{property.Name}", typeof(void), new[] { typeof(object), typeof(object) }, property.DeclaringType, true ); ILGenerator il = dynamicMethod.GetILGenerator(); if (setMethod.IsStatic) { il.Emit(OpCodes.Ldarg_1); il.Emit( property.PropertyType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, property.PropertyType ); il.Emit(OpCodes.Call, setMethod); } else { il.Emit(OpCodes.Ldarg_0); il.Emit( property.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, property.DeclaringType ); il.Emit(OpCodes.Ldarg_1); il.Emit( property.PropertyType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, property.PropertyType ); il.Emit( property.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt, setMethod ); } il.Emit(OpCodes.Ret); return (Action) dynamicMethod.CreateDelegate(typeof(Action)); } #endif /// /// Returns a compiled parameterless constructor delegate for a given . /// /// Type with a public parameterless constructor. /// Delegate: () => object instance /// If is null. /// If the type lacks a parameterless constructor. /// /// )); /// object list = ctor(); /// ]]> /// public static Func GetParameterlessConstructor(Type type) { if (type == null) { throw new ArgumentNullException(nameof(type)); } ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes); if (ctor == null) { throw new ArgumentException( $"Type {type.FullName} does not have a parameterless constructor" ); } return DelegateFactory.GetParameterlessConstructor(ctor); } /// /// Builds a cached delegate that returns the value of a static field as . /// /// Static field to read. /// Delegate: () => object value /// If is not static. public static Func GetStaticFieldGetter(FieldInfo field) { if (!field.IsStatic) { throw new ArgumentException(nameof(field)); } return DelegateFactory.GetStaticFieldGetter(field); } #if EMIT_DYNAMIC_IL private static Func BuildStaticFieldGetterIL(FieldInfo field) { DynamicMethod dynamicMethod = new( $"Get{field.DeclaringType.Name}_{field.Name}", typeof(object), Type.EmptyTypes, field.DeclaringType.Module, true ); ILGenerator il = dynamicMethod.GetILGenerator(); il.Emit(OpCodes.Ldsfld, field); if (field.FieldType.IsValueType) { il.Emit(OpCodes.Box, field.FieldType); } il.Emit(OpCodes.Ret); return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } #endif /// /// Builds a strongly-typed field getter delegate for instance fields. /// public static Func GetFieldGetter(FieldInfo field) { if (field == null) { throw new ArgumentNullException(nameof(field)); } return DelegateFactory.GetFieldGetterTyped(field); } /// /// Builds a cached delegate that returns the value of a static property as TValue. /// /// /// Builds a strongly-typed static property getter. /// /// Property value type. /// Static property to read. /// Delegate: () => TValue public static Func GetStaticPropertyGetter(PropertyInfo property) { return DelegateFactory.GetStaticPropertyGetterTyped(property); } /// /// Builds a cached delegate that returns the value of a static field as TValue. /// /// /// Builds a strongly-typed static field getter. /// /// Field value type. /// Static field. /// Delegate: () => TValue /// If the field is not static. public static Func GetStaticFieldGetter(FieldInfo field) { if (!field.IsStatic) { throw new ArgumentException(nameof(field)); } return DelegateFactory.GetStaticFieldGetterTyped(field); } /// /// Builds a strongly-typed field setter for instance fields. /// public static FieldSetter GetFieldSetter( FieldInfo field ) { if (field == null) { throw new ArgumentNullException(nameof(field)); } return DelegateFactory.GetFieldSetterTyped(field); } /// /// Builds a delegate that sets a static field to a value (boxed types supported). /// /// /// Builds a delegate that sets a static field to a value. /// /// Field value type. /// Static field to write. /// Delegate: (TValue value) => void /// If the field is not static. public static Action GetStaticFieldSetter(FieldInfo field) { if (!field.IsStatic) { throw new ArgumentException(nameof(field)); } return DelegateFactory.GetStaticFieldSetterTyped(field); } /// /// Builds a field setter for instance fields with boxed parameters (object instance, object value). /// /// /// Builds a field setter for fields with boxed parameters. /// Supports instance and static fields. /// /// Field to write. /// Delegate: (object instance, object value) => void public static Action GetFieldSetter(FieldInfo field) { return DelegateFactory.GetFieldSetter(field); } #if EMIT_DYNAMIC_IL private static Action BuildFieldSetterIL(FieldInfo field) { DynamicMethod dynamicMethod = new( $"SetField{field.DeclaringType.Name}_{field.Name}", null, new[] { typeof(object), typeof(object) }, field.DeclaringType.Module, true ); ILGenerator il = dynamicMethod.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit( field.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, field.DeclaringType ); il.Emit(OpCodes.Ldarg_1); il.Emit( field.FieldType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, field.FieldType ); il.Emit(OpCodes.Stfld, field); il.Emit(OpCodes.Ret); return (Action) dynamicMethod.CreateDelegate(typeof(Action)); } #endif /// /// Builds a static field setter with boxed parameter (object value). /// /// /// Builds a static field setter with boxed parameter. /// /// Static field to write. /// Delegate: (object value) => void /// If the field is not static. public static Action GetStaticFieldSetter(FieldInfo field) { if (!field.IsStatic) { throw new ArgumentException(nameof(field)); } return DelegateFactory.GetStaticFieldSetter(field); } #if EMIT_DYNAMIC_IL private static Action BuildStaticFieldSetterIL(FieldInfo field) { DynamicMethod dynamicMethod = new( $"SetFieldStatic{field.DeclaringType.Name}_{field.Name}", null, new[] { typeof(object) }, field.DeclaringType.Module, true ); ILGenerator il = dynamicMethod.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit( field.FieldType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, field.FieldType ); il.Emit(OpCodes.Stsfld, field); il.Emit(OpCodes.Ret); return (Action)dynamicMethod.CreateDelegate(typeof(Action)); } #endif /// /// Gets (or caches) an array creator function for the given element type and length. /// /// /// Gets (or caches) an array creator function for the given element type. /// /// Array element type. /// Delegate: (int length) => Array public static Func GetArrayCreator(Type elementType) { #if !EMIT_DYNAMIC_IL return size => { if (size < 0) { // Match IL newarr behavior which throws OverflowException for negative lengths throw new OverflowException("Array length must be non-negative."); } return Array.CreateInstance(elementType, size); }; #else DynamicMethod dynamicMethod = new( $"CreateArray{elementType.Name}", typeof(Array), // Return type: Array new[] { typeof(int) }, // Parameter: int (size) true ); ILGenerator il = dynamicMethod.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); // Load the array size il.Emit(OpCodes.Newarr, elementType); // Create a new array of 'type' il.Emit(OpCodes.Ret); // Return the array return (Func)dynamicMethod.CreateDelegate(typeof(Func)); #endif } /// /// Gets (or caches) a List<T> creator function for the given element type. /// /// /// Gets (or caches) a creator function for the given element type. /// /// List element type. /// Delegate: () => IList where the instance is a List<T>. public static Func GetListCreator(Type elementType) { Type listType = typeof(List<>).MakeGenericType(elementType); #if !EMIT_DYNAMIC_IL return () => (IList)Activator.CreateInstance(listType); #else DynamicMethod dynamicMethod = new( $"CreateList{listType.Name}", typeof(IList), // Return type: IList Type.EmptyTypes, // No parameters true ); ILGenerator il = dynamicMethod.GetILGenerator(); ConstructorInfo constructor = listType.GetConstructor(Type.EmptyTypes); if (constructor == null) { throw new ArgumentException( $"Type {listType} does not have a parameterless constructor." ); } il.Emit(OpCodes.Newobj, constructor); // Call List constructor il.Emit(OpCodes.Ret); // Return the instance return (Func)dynamicMethod.CreateDelegate(typeof(Func)); #endif } /// /// Gets (or caches) a List<T> creator function with capacity for the given element type. /// /// /// Gets (or caches) a creator function with capacity for the given element type. /// /// List element type. /// Delegate: (int capacity) => IList where the instance is a List<T>. public static Func GetListWithCapacityCreator(Type elementType) { Type listType = typeof(List<>).MakeGenericType(elementType); #if !EMIT_DYNAMIC_IL return capacity => (IList)Activator.CreateInstance(listType, capacity); #else DynamicMethod dynamicMethod = new( $"CreateListWithCapacity{listType.Name}", typeof(IList), // Return type: IList new[] { typeof(int) }, // Parameter: int (size) true ); ILGenerator il = dynamicMethod.GetILGenerator(); ConstructorInfo constructor = listType.GetConstructor(new[] { typeof(int) }); if (constructor == null) { throw new ArgumentException( $"Type {listType} does not have a constructor accepting an int." ); } il.Emit(OpCodes.Ldarg_0); // Load capacity argument il.Emit(OpCodes.Newobj, constructor); // Call List(int capacity) constructor il.Emit(OpCodes.Ret); // Return the instance return (Func)dynamicMethod.CreateDelegate(typeof(Func)); #endif } /// /// Creates a instance for the given element type with capacity. /// /// Element type for the set. /// Initial capacity. /// A boxed HashSet<T> as . /// /// /// ]]> /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static object CreateHashSet(Type elementType, int capacity) { return GetHashSetWithCapacityCreatorCached(elementType).Invoke(capacity); } /// /// Gets (or caches) a creator with capacity for the given element type. /// /// Element type for the set. /// Delegate: (int capacity) => object producing a boxed HashSet<T>. public static Func GetHashSetWithCapacityCreator(Type elementType) { Type hashSetType = typeof(HashSet<>).MakeGenericType(elementType); #if !EMIT_DYNAMIC_IL return capacity => Activator.CreateInstance(hashSetType, capacity); #else DynamicMethod dynamicMethod = new( $"CreateHashSetWithCapacity{hashSetType.Name}", typeof(object), // Return type: object new[] { typeof(int) }, // Parameter: int (capacity) true ); ILGenerator il = dynamicMethod.GetILGenerator(); ConstructorInfo constructor = hashSetType.GetConstructor(new[] { typeof(int) }); if (constructor == null) { throw new ArgumentException( $"Type {hashSetType} does not have a constructor accepting an int." ); } il.Emit(OpCodes.Ldarg_0); // Load capacity argument il.Emit(OpCodes.Newobj, constructor); // Call HashSet(int capacity) constructor il.Emit(OpCodes.Ret); // Return the instance return (Func)dynamicMethod.CreateDelegate(typeof(Func)); #endif } /// /// Gets (or caches) an adder delegate for HashSet<T>.Add. /// /// Element type for the target HashSet<T>. /// Delegate: (object hashSet, object item) => void /// /// /// public static Action GetHashSetAdder(Type elementType) { if (elementType == null) { throw new ArgumentNullException(nameof(elementType)); } Type hashSetType = typeof(HashSet<>).MakeGenericType(elementType); MethodInfo addMethod = hashSetType.GetMethod("Add", new[] { elementType }); if (addMethod == null) { throw new ArgumentException( $"Type {hashSetType} does not have an Add method accepting {elementType}.", nameof(elementType) ); } #if !EMIT_DYNAMIC_IL return CreateCompiledHashSetAdder(hashSetType, elementType, addMethod) ?? ( (set, value) => { // Mirror cast/unbox behavior to surface InvalidCastException for mismatches if (value == null) { if ( elementType.IsValueType && Nullable.GetUnderlyingType(elementType) == null ) { throw new InvalidCastException( $"Object of type 'null' cannot be converted to type '{elementType}'." ); } } else if (!elementType.IsInstanceOfType(value)) { throw new InvalidCastException( $"Object of type '{value.GetType()}' cannot be converted to type '{elementType}'." ); } addMethod.Invoke(set, new[] { value }); } ); #else try { DynamicMethod dynamicMethod = new( $"AddToHashSet{hashSetType.Name}", typeof(void), new[] { typeof(object), typeof(object) }, hashSetType.Module, true ); ILGenerator il = dynamicMethod.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Castclass, hashSetType); il.Emit(OpCodes.Ldarg_1); il.Emit( elementType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, elementType ); il.EmitCall(OpCodes.Callvirt, addMethod, null); il.Emit(OpCodes.Pop); il.Emit(OpCodes.Ret); return (Action) dynamicMethod.CreateDelegate(typeof(Action)); } catch { return CreateCompiledHashSetAdder(hashSetType, elementType, addMethod) ?? ((set, value) => addMethod.Invoke(set, new[] { value })); } #endif } public static Action GetHashSetClearer(Type elementType) { if (elementType == null) { throw new ArgumentNullException(nameof(elementType)); } return HashSetClearers.GetOrAdd( elementType, static type => { Type hashSetType = typeof(HashSet<>).MakeGenericType(type); MethodInfo clearMethod = hashSetType.GetMethod("Clear", Type.EmptyTypes); if (clearMethod == null) { return _ => { }; } #if SUPPORT_EXPRESSION_COMPILE if (ExpressionsEnabled) { try { ParameterExpression target = Expression.Parameter( typeof(object), "set" ); UnaryExpression cast = Expression.Convert(target, hashSetType); MethodCallExpression call = Expression.Call(cast, clearMethod); return Expression.Lambda>(call, target).Compile(); } catch { // Fall through to reflection fallback } } #endif MethodInfo closedMethod = clearMethod; return set => closedMethod.Invoke(set, Array.Empty()); } ); } /// /// Invokes an instance method using a cached invoker; avoids per-call reflection overhead. /// /// The instance method to invoke. /// The target instance. /// Optional parameters. /// The return value from the method, or null for void. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static object InvokeMethod( MethodInfo method, object instance, params object[] parameters ) { return DelegateFactory.GetMethodInvoker(method).Invoke(instance, parameters); } /// /// Invokes a static method using a cached invoker; avoids per-call reflection overhead. /// /// The static method to invoke. /// Optional parameters. /// The return value from the method, or null for void. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static object InvokeStaticMethod(MethodInfo method, params object[] parameters) { return DelegateFactory.GetStaticMethodInvoker(method).Invoke(parameters); } /// /// Creates an instance using a constructor via a cached delegate. /// /// Constructor to invoke. /// Constructor parameters. /// Created instance. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static object CreateInstance(ConstructorInfo constructor, params object[] parameters) { return DelegateFactory.GetConstructorInvoker(constructor).Invoke(parameters); } /// /// Constructs an instance using a cached constructor invoker and returns it as T. /// /// /// Creates an instance of using the best-matching constructor. /// /// Constructor parameters. /// Type to create. /// New instance of . /// /// (name, level); /// ]]> /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T CreateInstance(params object[] parameters) { Type type = typeof(T); Type[] parameterTypes = GetParameterTypes(parameters); ConstructorInfo constructor = type.GetConstructor(parameterTypes); if (constructor == null) { throw new ArgumentException($"No matching constructor found for type {type.Name}"); } return (T)CreateInstance(constructor, parameters); } /// /// Constructs an instance of a closed generic type built from the given definition and arguments. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T CreateGenericInstance( Type genericTypeDefinition, Type[] genericArguments, params object[] parameters ) { Type constructedType = genericTypeDefinition.MakeGenericType(genericArguments); Type[] parameterTypes = GetParameterTypes(parameters); ConstructorInfo constructor = constructedType.GetConstructor(parameterTypes); if (constructor == null) { throw new ArgumentException( $"No matching constructor found for type {constructedType.Name}" ); } return (T)CreateInstance(constructor, parameters); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Type[] GetParameterTypes(object[] parameters) { if (parameters == null || parameters.Length == 0) { return Type.EmptyTypes; } Type[] types = new Type[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { types[i] = parameters[i]?.GetType(); } return types; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool HasByRefParameter(ParameterInfo[] parameters) { for (int i = 0; i < parameters.Length; i++) { if (parameters[i].ParameterType.IsByRef) { return true; } } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool HasParameterTypeMismatch( ParameterInfo[] parameters, Type[] expectedTypes ) { for (int i = 0; i < parameters.Length; i++) { if (parameters[i].ParameterType != expectedTypes[i]) { return true; } } return false; } /// /// Gets (or caches) a fast method invoker for instance methods to avoid reflection per call. /// public static Func GetMethodInvoker(MethodInfo method) { if (method.IsStatic) { throw new ArgumentException( "Use GetStaticMethodInvoker for static methods", nameof(method) ); } return DelegateFactory.GetMethodInvoker(method); } /// /// Gets (or caches) a fast method invoker for static methods to avoid reflection per call. /// public static Func GetStaticMethodInvoker(MethodInfo method) { if (!method.IsStatic) { throw new ArgumentException("Method must be static", nameof(method)); } return DelegateFactory.GetStaticMethodInvoker(method); } /// /// Gets (or caches) a fast constructor invoker delegate that accepts an object[] of arguments. /// public static Func GetConstructor(ConstructorInfo constructor) { return DelegateFactory.GetConstructorInvoker(constructor); } /// /// Gets (or caches) a strongly-typed static method invoker with two parameters to avoid object[] allocations. /// Signature: Func<T1, T2, TReturn> /// /// First parameter type. /// Second parameter type. /// Return type. /// Static method info. /// Compiled delegate matching the method signature. public static Func GetStaticMethodInvoker( MethodInfo method ) { if (method == null) { throw new ArgumentNullException(nameof(method)); } if (!method.IsStatic) { throw new ArgumentException("Method must be static", nameof(method)); } ParameterInfo[] ps = method.GetParameters(); if ( ps.Length != 2 || ps[0].ParameterType != typeof(T1) || ps[1].ParameterType != typeof(T2) ) { throw new ArgumentException("Method signature does not match ."); } if (HasByRefParameter(ps)) { throw new NotSupportedException( "ref/out parameters are not supported in typed invokers" ); } return DelegateFactory.GetStaticMethodInvokerTyped(method); } public static Func GetArrayCreator() { return length => new T[length]; } public static Func GetListCreator() { return () => new List(); } public static Func GetListWithCapacityCreator() { return capacity => new List(capacity); } public static Func> GetHashSetWithCapacityCreator() { return capacity => new HashSet(capacity); } public static HashSet CreateHashSet(int capacity) { return new HashSet(capacity); } public static Action, T> GetHashSetAdder() { return (set, value) => set.Add(value); } public static object CreateDictionary(Type keyType, Type valueType, int capacity) { if (keyType == null || valueType == null) { throw new ArgumentNullException(); } Type dictType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType); #if !EMIT_DYNAMIC_IL return Activator.CreateInstance(dictType, capacity); #else DynamicMethod dm = new( $"CreateDict_{dictType.Name}", typeof(object), new[] { typeof(int) }, true ); ILGenerator il = dm.GetILGenerator(); ConstructorInfo ctor = dictType.GetConstructor(new[] { typeof(int) }); if (ctor == null) { throw new ArgumentException($"Type {dictType} has no (int) constructor"); } il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Newobj, ctor); il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Func)) is Func f ? f(capacity) : Activator.CreateInstance(dictType, capacity); #endif } public static Func GetDictionaryWithCapacityCreator( Type keyType, Type valueType ) { if (keyType == null || valueType == null) { throw new ArgumentNullException(); } Type dictType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType); #if !EMIT_DYNAMIC_IL return capacity => Activator.CreateInstance(dictType, capacity); #else DynamicMethod dm = new( $"CreateDict_{dictType.Name}", typeof(object), new[] { typeof(int) }, true ); ILGenerator il = dm.GetILGenerator(); ConstructorInfo ctor = dictType.GetConstructor(new[] { typeof(int) }); if (ctor == null) { throw new ArgumentException($"Type {dictType} has no (int) constructor"); } il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Newobj, ctor); il.Emit(OpCodes.Ret); return (Func)dm.CreateDelegate(typeof(Func)); #endif } public static Func> GetDictionaryCreator() { return capacity => new Dictionary(capacity); } public static Func GetStaticMethodInvoker(MethodInfo method) { if (method == null) { throw new ArgumentNullException(nameof(method)); } if (!method.IsStatic) { throw new ArgumentException("Method must be static", nameof(method)); } if (method.GetParameters().Length != 0 || method.ReturnType != typeof(TReturn)) { throw new ArgumentException("Method signature does not match ."); } return DelegateFactory.GetStaticMethodInvokerTyped(method); } public static Func GetStaticMethodInvoker(MethodInfo method) { if (method == null) { throw new ArgumentNullException(nameof(method)); } if (!method.IsStatic) { throw new ArgumentException("Method must be static", nameof(method)); } ParameterInfo[] ps = method.GetParameters(); if (ps.Length != 1 || ps[0].ParameterType != typeof(T1)) { throw new ArgumentException("Method signature does not match ."); } if (HasByRefParameter(ps)) { throw new NotSupportedException( "ref/out parameters are not supported in typed invokers" ); } return DelegateFactory.GetStaticMethodInvokerTyped(method); } public static Func GetStaticMethodInvoker( MethodInfo method ) { if (method == null) { throw new ArgumentNullException(nameof(method)); } if (!method.IsStatic) { throw new ArgumentException("Method must be static", nameof(method)); } ParameterInfo[] ps = method.GetParameters(); if ( ps.Length != 3 || ps[0].ParameterType != typeof(T1) || ps[1].ParameterType != typeof(T2) || ps[2].ParameterType != typeof(T3) ) { throw new ArgumentException("Method signature does not match ."); } if (HasByRefParameter(ps)) { throw new NotSupportedException( "ref/out parameters are not supported in typed invokers" ); } return DelegateFactory.GetStaticMethodInvokerTyped(method); } public static Func GetStaticMethodInvoker( MethodInfo method ) { if (method == null) { throw new ArgumentNullException(nameof(method)); } if (!method.IsStatic) { throw new ArgumentException("Method must be static", nameof(method)); } ParameterInfo[] ps = method.GetParameters(); if ( ps.Length != 4 || ps[0].ParameterType != typeof(T1) || ps[1].ParameterType != typeof(T2) || ps[2].ParameterType != typeof(T3) || ps[3].ParameterType != typeof(T4) ) { throw new ArgumentException( "Method signature does not match ." ); } if (HasByRefParameter(ps)) { throw new NotSupportedException( "ref/out parameters are not supported in typed invokers" ); } return DelegateFactory.GetStaticMethodInvokerTyped(method); } public static Action GetStaticActionInvoker(MethodInfo method) { ValidateStaticActionSignature(method); return DelegateFactory.GetStaticActionInvokerTyped(method); } public static Action GetStaticActionInvoker(MethodInfo method) { ValidateStaticActionSignature(method, typeof(T1)); return DelegateFactory.GetStaticActionInvokerTyped(method); } public static Action GetStaticActionInvoker(MethodInfo method) { ValidateStaticActionSignature(method, typeof(T1), typeof(T2)); return DelegateFactory.GetStaticActionInvokerTyped(method); } public static Action GetStaticActionInvoker(MethodInfo method) { ValidateStaticActionSignature(method, typeof(T1), typeof(T2), typeof(T3)); return DelegateFactory.GetStaticActionInvokerTyped(method); } public static Action GetStaticActionInvoker( MethodInfo method ) { ValidateStaticActionSignature(method, typeof(T1), typeof(T2), typeof(T3), typeof(T4)); return DelegateFactory.GetStaticActionInvokerTyped(method); } public static Func GetInstanceMethodInvoker( MethodInfo method ) { ValidateInstanceFuncSignature(method, Type.EmptyTypes); return DelegateFactory.GetInstanceMethodInvokerTyped(method); } public static Func GetInstanceMethodInvoker( MethodInfo method ) { ValidateInstanceFuncSignature(method, new[] { typeof(T1) }); return DelegateFactory.GetInstanceMethodInvokerTyped(method); } public static Func GetInstanceMethodInvoker< TInstance, T1, T2, TReturn >(MethodInfo method) { ValidateInstanceFuncSignature( method, new[] { typeof(T1), typeof(T2) } ); return DelegateFactory.GetInstanceMethodInvokerTyped( method ); } public static Func GetInstanceMethodInvoker< TInstance, T1, T2, T3, TReturn >(MethodInfo method) { ValidateInstanceFuncSignature( method, new[] { typeof(T1), typeof(T2), typeof(T3) } ); return DelegateFactory.GetInstanceMethodInvokerTyped( method ); } public static Func GetInstanceMethodInvoker< TInstance, T1, T2, T3, T4, TReturn >(MethodInfo method) { ValidateInstanceFuncSignature( method, new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) } ); return DelegateFactory.GetInstanceMethodInvokerTyped< TInstance, T1, T2, T3, T4, TReturn >(method); } public static Action GetInstanceActionInvoker(MethodInfo method) { ValidateInstanceActionSignature(method, Type.EmptyTypes); return DelegateFactory.GetInstanceActionInvokerTyped(method); } public static Action GetInstanceActionInvoker( MethodInfo method ) { ValidateInstanceActionSignature(method, new[] { typeof(T1) }); return DelegateFactory.GetInstanceActionInvokerTyped(method); } public static Action GetInstanceActionInvoker( MethodInfo method ) { ValidateInstanceActionSignature(method, new[] { typeof(T1), typeof(T2) }); return DelegateFactory.GetInstanceActionInvokerTyped(method); } public static Action GetInstanceActionInvoker( MethodInfo method ) { ValidateInstanceActionSignature( method, new[] { typeof(T1), typeof(T2), typeof(T3) } ); return DelegateFactory.GetInstanceActionInvokerTyped(method); } public static Action GetInstanceActionInvoker< TInstance, T1, T2, T3, T4 >(MethodInfo method) { ValidateInstanceActionSignature( method, new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) } ); return DelegateFactory.GetInstanceActionInvokerTyped(method); } private static Delegate BuildTypedStaticInvoker2(MethodInfo method) { if (ExpressionsEnabled) { try { ParameterExpression p1 = Expression.Parameter(typeof(T1), "a"); ParameterExpression p2 = Expression.Parameter(typeof(T2), "b"); MethodCallExpression call = Expression.Call(method, p1, p2); return Expression.Lambda>(call, p1, p2).Compile(); } catch { // continue to alternative strategies } } #if EMIT_DYNAMIC_IL if (DynamicIlEnabled) { try { DynamicMethod dm = new( $"InvokeStatic2_{method.DeclaringType?.Name}_{method.Name}", typeof(TReturn), new[] { typeof(T1), typeof(T2) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Call, method); il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Func)); } catch { // ignore and fall back to reflection } } #endif try { return method.CreateDelegate(typeof(Func)); } catch { return new Func( (a, b) => (TReturn)method.Invoke(null, new object[] { a, b }) ); } } private static Delegate BuildTypedStaticInvoker0(MethodInfo method) { if (ExpressionsEnabled) { try { MethodCallExpression call = Expression.Call(method); return Expression.Lambda>(call).Compile(); } catch { // Fall through to alternative strategies } } #if EMIT_DYNAMIC_IL if (DynamicIlEnabled) { try { DynamicMethod dm = new( $"InvokeStatic0_{method.DeclaringType?.Name}_{method.Name}", typeof(TReturn), Type.EmptyTypes, method.Module, true ); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Call, method); il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Func)); } catch { // Ignore and fall back to reflection } } #endif try { return method.CreateDelegate(typeof(Func)); } catch { return new Func(() => (TReturn)method.Invoke(null, Array.Empty())); } } private static Delegate BuildTypedStaticInvoker1(MethodInfo method) { if (ExpressionsEnabled) { try { ParameterExpression a = Expression.Parameter(typeof(T1), "a"); MethodCallExpression call = Expression.Call(method, a); return Expression.Lambda>(call, a).Compile(); } catch { // Continue to alternative strategies } } #if EMIT_DYNAMIC_IL if (DynamicIlEnabled) { try { DynamicMethod dm = new( $"InvokeStatic1_{method.DeclaringType?.Name}_{method.Name}", typeof(TReturn), new[] { typeof(T1) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, method); il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Func)); } catch { // fall through } } #endif try { return method.CreateDelegate(typeof(Func)); } catch { return new Func(arg => (TReturn)method.Invoke(null, new object[] { arg }) ); } } private static Delegate BuildTypedStaticInvoker3(MethodInfo method) { #if !EMIT_DYNAMIC_IL try { return method.CreateDelegate(typeof(Func)); } catch { ParameterExpression a = Expression.Parameter(typeof(T1), "a"); ParameterExpression b = Expression.Parameter(typeof(T2), "b"); ParameterExpression c = Expression.Parameter(typeof(T3), "c"); MethodCallExpression call = Expression.Call(method, a, b, c); return Expression.Lambda>(call, a, b, c).Compile(); } #else DynamicMethod dm = new( $"InvokeStatic3_{method.DeclaringType?.Name}_{method.Name}", typeof(TReturn), new[] { typeof(T1), typeof(T2), typeof(T3) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Call, method); il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Func)); #endif } private static Delegate BuildTypedStaticInvoker4(MethodInfo method) { #if !EMIT_DYNAMIC_IL try { return method.CreateDelegate(typeof(Func)); } catch { ParameterExpression a = Expression.Parameter(typeof(T1), "a"); ParameterExpression b = Expression.Parameter(typeof(T2), "b"); ParameterExpression c = Expression.Parameter(typeof(T3), "c"); ParameterExpression d = Expression.Parameter(typeof(T4), "d"); MethodCallExpression call = Expression.Call(method, a, b, c, d); return Expression.Lambda>(call, a, b, c, d).Compile(); } #else DynamicMethod dm = new( $"InvokeStatic4_{method.DeclaringType?.Name}_{method.Name}", typeof(TReturn), new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_3); il.Emit(OpCodes.Call, method); il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Func)); #endif } private static Delegate BuildStaticActionInvoker0(MethodInfo method) { #if !EMIT_DYNAMIC_IL try { return method.CreateDelegate(typeof(Action)); } catch { MethodCallExpression call = Expression.Call(method); return Expression.Lambda(call).Compile(); } #else DynamicMethod dm = new( $"InvokeStaticA0_{method.DeclaringType?.Name}_{method.Name}", typeof(void), Type.EmptyTypes, method.Module, true ); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Call, method); il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Action)); #endif } private static Delegate BuildStaticActionInvoker1(MethodInfo method) { #if !EMIT_DYNAMIC_IL try { return method.CreateDelegate(typeof(Action)); } catch { ParameterExpression a = Expression.Parameter(typeof(T1), "a"); MethodCallExpression call = Expression.Call(method, a); return Expression.Lambda>(call, a).Compile(); } #else DynamicMethod dm = new( $"InvokeStaticA1_{method.DeclaringType?.Name}_{method.Name}", typeof(void), new[] { typeof(T1) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, method); il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Action)); #endif } private static Delegate BuildStaticActionInvoker2(MethodInfo method) { #if !EMIT_DYNAMIC_IL try { return method.CreateDelegate(typeof(Action)); } catch { ParameterExpression a = Expression.Parameter(typeof(T1), "a"); ParameterExpression b = Expression.Parameter(typeof(T2), "b"); MethodCallExpression call = Expression.Call(method, a, b); return Expression.Lambda>(call, a, b).Compile(); } #else DynamicMethod dm = new( $"InvokeStaticA2_{method.DeclaringType?.Name}_{method.Name}", typeof(void), new[] { typeof(T1), typeof(T2) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Call, method); il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Action)); #endif } private static Delegate BuildStaticActionInvoker3(MethodInfo method) { #if !EMIT_DYNAMIC_IL try { return method.CreateDelegate(typeof(Action)); } catch { ParameterExpression a = Expression.Parameter(typeof(T1), "a"); ParameterExpression b = Expression.Parameter(typeof(T2), "b"); ParameterExpression c = Expression.Parameter(typeof(T3), "c"); MethodCallExpression call = Expression.Call(method, a, b, c); return Expression.Lambda>(call, a, b, c).Compile(); } #else DynamicMethod dm = new( $"InvokeStaticA3_{method.DeclaringType?.Name}_{method.Name}", typeof(void), new[] { typeof(T1), typeof(T2), typeof(T3) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Call, method); il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Action)); #endif } private static Delegate BuildStaticActionInvoker4(MethodInfo method) { #if !EMIT_DYNAMIC_IL try { return method.CreateDelegate(typeof(Action)); } catch { ParameterExpression a = Expression.Parameter(typeof(T1), "a"); ParameterExpression b = Expression.Parameter(typeof(T2), "b"); ParameterExpression c = Expression.Parameter(typeof(T3), "c"); ParameterExpression d = Expression.Parameter(typeof(T4), "d"); MethodCallExpression call = Expression.Call(method, a, b, c, d); return Expression.Lambda>(call, a, b, c, d).Compile(); } #else DynamicMethod dm = new( $"InvokeStaticA4_{method.DeclaringType?.Name}_{method.Name}", typeof(void), new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_3); il.Emit(OpCodes.Call, method); il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Action)); #endif } private static void ValidateStaticActionSignature( MethodInfo method, params Type[] parameters ) { if (method == null) { throw new ArgumentNullException(nameof(method)); } if (!method.IsStatic) { throw new ArgumentException("Method must be static", nameof(method)); } if (method.ReturnType != typeof(void)) { throw new ArgumentException("Action invoker requires void return type"); } ParameterInfo[] ps = method.GetParameters(); if (HasByRefParameter(ps)) { throw new NotSupportedException( "ref/out parameters are not supported in typed invokers" ); } if (ps.Length != parameters.Length || HasParameterTypeMismatch(ps, parameters)) { throw new ArgumentException("Method signature does not match Action parameters"); } } private static void ValidateInstanceFuncSignature( MethodInfo method, Type[] parameterTypes ) { if (method == null) { throw new ArgumentNullException(nameof(method)); } if (method.IsStatic) { throw new ArgumentException("Method must be instance", nameof(method)); } if (method.ReturnType != typeof(TReturn)) { throw new ArgumentException("Return type mismatch"); } if (!typeof(TInstance).IsAssignableFrom(method.DeclaringType)) { throw new ArgumentException("Instance type mismatch"); } ParameterInfo[] ps = method.GetParameters(); if (HasByRefParameter(ps)) { throw new NotSupportedException( "ref/out parameters are not supported in typed invokers" ); } if (ps.Length != parameterTypes.Length || HasParameterTypeMismatch(ps, parameterTypes)) { throw new ArgumentException("Method parameters mismatch"); } } private static void ValidateInstanceActionSignature( MethodInfo method, Type[] parameterTypes ) { if (method == null) { throw new ArgumentNullException(nameof(method)); } if (method.IsStatic) { throw new ArgumentException("Method must be instance", nameof(method)); } if (method.ReturnType != typeof(void)) { throw new ArgumentException("Return type must be void for Action invoker"); } if (!typeof(TInstance).IsAssignableFrom(method.DeclaringType)) { throw new ArgumentException("Instance type mismatch"); } ParameterInfo[] ps = method.GetParameters(); if (HasByRefParameter(ps)) { throw new NotSupportedException( "ref/out parameters are not supported in typed invokers" ); } if (ps.Length != parameterTypes.Length || HasParameterTypeMismatch(ps, parameterTypes)) { throw new ArgumentException("Method parameters mismatch"); } } #if !EMIT_DYNAMIC_IL private static Delegate BuildInstanceInvoker0(MethodInfo method) { try { return method.CreateDelegate(typeof(Func)); } catch { ParameterExpression inst = Expression.Parameter(typeof(TInstance), "instance"); MethodCallExpression call = Expression.Call(inst, method); return Expression.Lambda>(call, inst).Compile(); } } private static Delegate BuildInstanceInvoker1(MethodInfo method) { try { return method.CreateDelegate(typeof(Func)); } catch { ParameterExpression inst = Expression.Parameter(typeof(TInstance), "instance"); ParameterExpression a = Expression.Parameter(typeof(T1), "a"); MethodCallExpression call = Expression.Call(inst, method, a); return Expression.Lambda>(call, inst, a).Compile(); } } private static Delegate BuildInstanceInvoker2(MethodInfo method) { try { return method.CreateDelegate(typeof(Func)); } catch { ParameterExpression inst = Expression.Parameter(typeof(TInstance), "instance"); ParameterExpression a = Expression.Parameter(typeof(T1), "a"); ParameterExpression b = Expression.Parameter(typeof(T2), "b"); MethodCallExpression call = Expression.Call(inst, method, a, b); return Expression .Lambda>(call, inst, a, b) .Compile(); } } private static Delegate BuildInstanceInvoker3( MethodInfo method ) { try { return method.CreateDelegate(typeof(Func)); } catch { ParameterExpression inst = Expression.Parameter(typeof(TInstance), "instance"); ParameterExpression a = Expression.Parameter(typeof(T1), "a"); ParameterExpression b = Expression.Parameter(typeof(T2), "b"); ParameterExpression c = Expression.Parameter(typeof(T3), "c"); MethodCallExpression call = Expression.Call(inst, method, a, b, c); return Expression .Lambda>(call, inst, a, b, c) .Compile(); } } private static Delegate BuildInstanceInvoker4( MethodInfo method ) { try { return method.CreateDelegate(typeof(Func)); } catch { ParameterExpression inst = Expression.Parameter(typeof(TInstance), "instance"); ParameterExpression a = Expression.Parameter(typeof(T1), "a"); ParameterExpression b = Expression.Parameter(typeof(T2), "b"); ParameterExpression c = Expression.Parameter(typeof(T3), "c"); ParameterExpression d = Expression.Parameter(typeof(T4), "d"); MethodCallExpression call = Expression.Call(inst, method, a, b, c, d); return Expression .Lambda>(call, inst, a, b, c, d) .Compile(); } } private static Delegate BuildInstanceActionInvoker0(MethodInfo method) { try { return method.CreateDelegate(typeof(Action)); } catch { ParameterExpression inst = Expression.Parameter(typeof(TInstance), "instance"); MethodCallExpression call = Expression.Call(inst, method); return Expression.Lambda>(call, inst).Compile(); } } private static Delegate BuildInstanceActionInvoker1(MethodInfo method) { try { return method.CreateDelegate(typeof(Action)); } catch { ParameterExpression inst = Expression.Parameter(typeof(TInstance), "instance"); ParameterExpression a = Expression.Parameter(typeof(T1), "a"); MethodCallExpression call = Expression.Call(inst, method, a); return Expression.Lambda>(call, inst, a).Compile(); } } private static Delegate BuildInstanceActionInvoker2(MethodInfo method) { try { return method.CreateDelegate(typeof(Action)); } catch { ParameterExpression inst = Expression.Parameter(typeof(TInstance), "instance"); ParameterExpression a = Expression.Parameter(typeof(T1), "a"); ParameterExpression b = Expression.Parameter(typeof(T2), "b"); MethodCallExpression call = Expression.Call(inst, method, a, b); return Expression.Lambda>(call, inst, a, b).Compile(); } } private static Delegate BuildInstanceActionInvoker3( MethodInfo method ) { try { return method.CreateDelegate(typeof(Action)); } catch { ParameterExpression inst = Expression.Parameter(typeof(TInstance), "instance"); ParameterExpression a = Expression.Parameter(typeof(T1), "a"); ParameterExpression b = Expression.Parameter(typeof(T2), "b"); ParameterExpression c = Expression.Parameter(typeof(T3), "c"); MethodCallExpression call = Expression.Call(inst, method, a, b, c); return Expression .Lambda>(call, inst, a, b, c) .Compile(); } } private static Delegate BuildInstanceActionInvoker4( MethodInfo method ) { try { return method.CreateDelegate(typeof(Action)); } catch { ParameterExpression inst = Expression.Parameter(typeof(TInstance), "instance"); ParameterExpression a = Expression.Parameter(typeof(T1), "a"); ParameterExpression b = Expression.Parameter(typeof(T2), "b"); ParameterExpression c = Expression.Parameter(typeof(T3), "c"); ParameterExpression d = Expression.Parameter(typeof(T4), "d"); MethodCallExpression call = Expression.Call(inst, method, a, b, c, d); return Expression .Lambda>(call, inst, a, b, c, d) .Compile(); } } #else private static Delegate BuildInstanceInvoker0(MethodInfo method) { DynamicMethod dm = new( $"InvokeInst0_{method.DeclaringType?.Name}_{method.Name}", typeof(TReturn), new[] { typeof(TInstance) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); if (typeof(TInstance).IsValueType) { il.Emit(OpCodes.Ldarga_S, (byte)0); il.Emit(OpCodes.Call, method); } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Callvirt, method); } il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Func)); } private static Delegate BuildInstanceInvoker1(MethodInfo method) { DynamicMethod dm = new( $"InvokeInst1_{method.DeclaringType?.Name}_{method.Name}", typeof(TReturn), new[] { typeof(TInstance), typeof(T1) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); if (typeof(TInstance).IsValueType) { il.Emit(OpCodes.Ldarga_S, (byte)0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Call, method); } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Callvirt, method); } il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Func)); } private static Delegate BuildInstanceInvoker2(MethodInfo method) { DynamicMethod dm = new( $"InvokeInst2_{method.DeclaringType?.Name}_{method.Name}", typeof(TReturn), new[] { typeof(TInstance), typeof(T1), typeof(T2) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); if (typeof(TInstance).IsValueType) { il.Emit(OpCodes.Ldarga_S, (byte)0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Call, method); } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Callvirt, method); } il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Func)); } private static Delegate BuildInstanceInvoker3( MethodInfo method ) { DynamicMethod dm = new( $"InvokeInst3_{method.DeclaringType?.Name}_{method.Name}", typeof(TReturn), new[] { typeof(TInstance), typeof(T1), typeof(T2), typeof(T3) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); if (typeof(TInstance).IsValueType) { il.Emit(OpCodes.Ldarga_S, (byte)0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_3); il.Emit(OpCodes.Call, method); } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_3); il.Emit(OpCodes.Callvirt, method); } il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Func)); } private static Delegate BuildInstanceInvoker4( MethodInfo method ) { DynamicMethod dm = new( $"InvokeInst4_{method.DeclaringType?.Name}_{method.Name}", typeof(TReturn), new[] { typeof(TInstance), typeof(T1), typeof(T2), typeof(T3), typeof(T4) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); if (typeof(TInstance).IsValueType) { il.Emit(OpCodes.Ldarga_S, (byte)0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_3); il.Emit(OpCodes.Ldarg_S, (byte)4); il.Emit(OpCodes.Call, method); } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_3); il.Emit(OpCodes.Ldarg_S, (byte)4); il.Emit(OpCodes.Callvirt, method); } il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Func)); } private static Delegate BuildInstanceActionInvoker0(MethodInfo method) { DynamicMethod dm = new( $"InvokeInstA0_{method.DeclaringType?.Name}_{method.Name}", typeof(void), new[] { typeof(TInstance) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); if (typeof(TInstance).IsValueType) { il.Emit(OpCodes.Ldarga_S, (byte)0); il.Emit(OpCodes.Call, method); } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Callvirt, method); } il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Action)); } private static Delegate BuildInstanceActionInvoker1(MethodInfo method) { DynamicMethod dm = new( $"InvokeInstA1_{method.DeclaringType?.Name}_{method.Name}", typeof(void), new[] { typeof(TInstance), typeof(T1) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); if (typeof(TInstance).IsValueType) { il.Emit(OpCodes.Ldarga_S, (byte)0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Call, method); } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Callvirt, method); } il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Action)); } private static Delegate BuildInstanceActionInvoker2(MethodInfo method) { DynamicMethod dm = new( $"InvokeInstA2_{method.DeclaringType?.Name}_{method.Name}", typeof(void), new[] { typeof(TInstance), typeof(T1), typeof(T2) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); if (typeof(TInstance).IsValueType) { il.Emit(OpCodes.Ldarga_S, (byte)0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Call, method); } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Callvirt, method); } il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Action)); } private static Delegate BuildInstanceActionInvoker3( MethodInfo method ) { DynamicMethod dm = new( $"InvokeInstA3_{method.DeclaringType?.Name}_{method.Name}", typeof(void), new[] { typeof(TInstance), typeof(T1), typeof(T2), typeof(T3) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); if (typeof(TInstance).IsValueType) { il.Emit(OpCodes.Ldarga_S, (byte)0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_3); il.Emit(OpCodes.Call, method); } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_3); il.Emit(OpCodes.Callvirt, method); } il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Action)); } private static Delegate BuildInstanceActionInvoker4( MethodInfo method ) { DynamicMethod dm = new( $"InvokeInstA4_{method.DeclaringType?.Name}_{method.Name}", typeof(void), new[] { typeof(TInstance), typeof(T1), typeof(T2), typeof(T3), typeof(T4) }, method.Module, true ); ILGenerator il = dm.GetILGenerator(); if (typeof(TInstance).IsValueType) { il.Emit(OpCodes.Ldarga_S, (byte)0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_3); il.Emit(OpCodes.Ldarg_S, (byte)4); il.Emit(OpCodes.Call, method); } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldarg_3); il.Emit(OpCodes.Ldarg_S, (byte)4); il.Emit(OpCodes.Callvirt, method); } il.Emit(OpCodes.Ret); return dm.CreateDelegate(typeof(Action)); } #endif /// /// Gets a parameterless constructor delegate for type T, or throws if not present. /// /// /// Gets a parameterless constructor delegate for type T, or throws if not present. /// public static Func GetParameterlessConstructor() { Type type = typeof(T); ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes); if (constructor == null) { throw new ArgumentException( $"Type {type.Name} does not have a parameterless constructor" ); } return DelegateFactory.GetParameterlessConstructorTyped(constructor); } /// /// Gets a parameterless constructor delegate for a closed generic type constructed from the given generic definition and arguments. /// public static Func GetGenericParameterlessConstructor( Type genericTypeDefinition, params Type[] genericArguments ) { Type constructedType = genericTypeDefinition.MakeGenericType(genericArguments); ConstructorInfo constructor = constructedType.GetConstructor(Type.EmptyTypes); if (constructor == null) { throw new ArgumentException( $"Type {constructedType.Name} does not have a parameterless constructor" ); } return DelegateFactory.GetParameterlessConstructorTyped(constructor); } // Type discovery methods moved to ReflectionHelpers.TypeDiscovery.cs public static bool HasAttributeSafe( ICustomAttributeProvider provider, bool inherit = true ) where TAttribute : Attribute { if (provider == null) { return false; } try { return provider.IsDefined(typeof(TAttribute), inherit); } catch { return false; } } public static Action BuildParameterlessInstanceMethodIfExists(string methodName) { try { Type type = typeof(T); foreach ( MethodInfo method in type.GetMethods( BindingFlags.Instance | BindingFlags.Public ) ) { if ( string.Equals(method.Name, methodName, StringComparison.Ordinal) && method.GetParameters().Length == 0 ) { return (Action)Delegate.CreateDelegate(typeof(Action), method); } } } catch { // Swallow } return null; } #if SINGLE_THREADED private static readonly Dictionary> EnabledPropertyGetters = new(); [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Func GetEnabledPropertyGetterCached(Type componentType) { if (!EnabledPropertyGetters.TryGetValue(componentType, out Func getter)) { getter = BuildEnabledPropertyGetter(componentType); EnabledPropertyGetters[componentType] = getter; } return getter; } #else private static readonly ConcurrentDictionary< Type, Func > EnabledPropertyGetters = new(); [MethodImpl(MethodImplOptions.AggressiveInlining)] private static Func GetEnabledPropertyGetterCached(Type componentType) { return EnabledPropertyGetters.GetOrAdd( componentType, static type => BuildEnabledPropertyGetter(type) ); } #endif private static Func BuildEnabledPropertyGetter(Type type) { try { PropertyInfo property = type.GetProperty( EnabledPropertyName, BindingFlags.Instance | BindingFlags.Public ); if (property == null || property.PropertyType != typeof(bool)) { return null; } MethodInfo getMethod = property.GetGetMethod(); if (getMethod == null) { return null; } #if !EMIT_DYNAMIC_IL return CreateCompiledEnabledPropertyGetter(property, type); #else DynamicMethod dynamicMethod = new( $"GetEnabled_{type.Name}", typeof(bool), new[] { typeof(object) }, type, true ); ILGenerator il = dynamicMethod.GetILGenerator(); // Load and cast the instance argument il.Emit(OpCodes.Ldarg_0); il.Emit(type.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, type); // Call the getter il.Emit(type.IsValueType ? OpCodes.Call : OpCodes.Callvirt, getMethod); il.Emit(OpCodes.Ret); return (Func)dynamicMethod.CreateDelegate(typeof(Func)); #endif } catch { return null; } } private static Func CreateCompiledEnabledPropertyGetter( PropertyInfo property, Type type ) { if (!ExpressionsEnabled) { return CreateDelegateEnabledPropertyGetter(property, type) ?? (instance => (bool)property.GetValue(instance)); } try { MethodInfo getMethod = property.GetGetMethod(); if (getMethod == null) { return instance => (bool)property.GetValue(instance); } ParameterExpression instanceParam = Expression.Parameter( typeof(object), "instance" ); Expression instanceExpression = type.IsValueType ? Expression.Unbox(instanceParam, type) : Expression.Convert(instanceParam, type); Expression propertyExpression = Expression.Property(instanceExpression, property); return Expression .Lambda>(propertyExpression, instanceParam) .Compile(); } catch { return instance => (bool)property.GetValue(instance); } } private static Func CreateDelegateEnabledPropertyGetter( PropertyInfo property, Type type ) { try { MethodInfo getMethod = property.GetGetMethod(); if (getMethod == null) { return null; } // Try to create a delegate directly Type delegateType = typeof(Func<,>).MakeGenericType(type, typeof(bool)); Delegate del = Delegate.CreateDelegate(delegateType, null, getMethod, false); if (del == null) { return null; } return instance => (bool)del.DynamicInvoke(instance); } catch { return null; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsComponentEnabled(this T component) where T : UnityEngine.Object { if (component == null) { return false; } Type componentType = component.GetType(); Func enabledGetter = GetEnabledPropertyGetterCached(componentType); if (enabledGetter == null) { return true; } try { return enabledGetter(component); } catch { return true; } } public static bool IsActiveAndEnabled(this T component) where T : UnityEngine.Object { if (component == null) { return false; } bool enabled = component.IsComponentEnabled(); if (component is UnityEngine.Component c) { return enabled && c.gameObject != null && c.gameObject.activeInHierarchy; } return enabled; } public static bool HasAttributeSafe( ICustomAttributeProvider provider, Type attributeType, bool inherit = true ) { if (provider == null || attributeType == null) { return false; } try { return provider.IsDefined(attributeType, inherit); } catch { return false; } } public static bool TryGetAttributeSafe( ICustomAttributeProvider provider, out TAttribute attribute, bool inherit = true ) where TAttribute : Attribute { attribute = default; if (provider == null) { return false; } try { if (!provider.IsDefined(typeof(TAttribute), inherit)) { return false; } object[] attributes = provider.GetCustomAttributes(typeof(TAttribute), inherit); if (attributes == null || attributes.Length == 0) { return false; } for (int index = 0; index < attributes.Length; index++) { if (attributes[index] is TAttribute typed) { attribute = typed; return true; } } } catch { attribute = default; return false; } attribute = default; return false; } public static bool TryGetAttributeSafe( ICustomAttributeProvider provider, Type attributeType, out Attribute attribute, bool inherit = true ) { attribute = null; if (provider == null || attributeType == null) { return false; } try { if (!provider.IsDefined(attributeType, inherit)) { return false; } object[] attributes = provider.GetCustomAttributes(attributeType, inherit); if (attributes == null || attributes.Length == 0) { return false; } for (int index = 0; index < attributes.Length; index++) { if (attributes[index] is Attribute typed) { attribute = typed; return true; } } } catch { attribute = null; return false; } attribute = null; return false; } public static TAttribute GetAttributeSafe( ICustomAttributeProvider provider, bool inherit = true ) where TAttribute : Attribute { return TryGetAttributeSafe(provider, out TAttribute attribute, inherit) ? attribute : default; } public static Attribute GetAttributeSafe( ICustomAttributeProvider provider, Type attributeType, bool inherit = true ) { return TryGetAttributeSafe(provider, attributeType, out Attribute attribute, inherit) ? attribute : null; } public static TAttribute[] GetAllAttributesSafe( this ICustomAttributeProvider provider, bool inherit = true ) where TAttribute : Attribute { if (provider == null) { return Array.Empty(); } try { if (provider.IsDefined(typeof(TAttribute), inherit)) { object[] attributes = provider.GetCustomAttributes(typeof(TAttribute), inherit); using PooledResource> lease = Buffers.List.Get( out List result ); for (int i = 0; i < attributes.Length; i++) { if (attributes[i] is TAttribute attr) { result.Add(attr); } } return result.ToArray(); } return Array.Empty(); } catch { return Array.Empty(); } } public static Attribute[] GetAllAttributesSafe( this ICustomAttributeProvider provider, bool inherit = true ) { if (provider == null) { return Array.Empty(); } try { object[] attributes = provider.GetCustomAttributes(inherit); using PooledResource> lease = Buffers.List.Get( out List result ); for (int i = 0; i < attributes.Length; i++) { if (attributes[i] is Attribute attr) { result.Add(attr); } } return result.ToArray(); } catch { return Array.Empty(); } } public static Attribute[] GetAllAttributesSafe( this ICustomAttributeProvider provider, Type attributeType, bool inherit = true ) { if (provider == null || attributeType == null) { return Array.Empty(); } try { if (provider.IsDefined(attributeType, inherit)) { object[] attributes = provider.GetCustomAttributes(attributeType, inherit); using PooledResource> lease = Buffers.List.Get( out List result ); for (int i = 0; i < attributes.Length; i++) { if (attributes[i] is Attribute attr) { result.Add(attr); } } return result.ToArray(); } return Array.Empty(); } catch { return Array.Empty(); } } public static Dictionary GetAllAttributeValuesSafe( this ICustomAttributeProvider provider, bool inherit = true ) { Dictionary result = new(); foreach (Attribute attr in provider.GetAllAttributesSafe(inherit)) { try { Type attrType = attr.GetType(); string key = attrType.Name; if (key.EndsWith("Attribute")) { key = key.Substring(0, key.Length - 9); } result.TryAdd(key, attr); } catch { // Skip this attribute if we can't process it } } return result; } public static MethodInfo[] GetMethodsWithAttributeSafe( this Type type, bool inherit = true ) where TAttribute : Attribute { if (type == null) { return Array.Empty(); } try { MethodInfo[] methods = type.GetMethods( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static ); using PooledResource> lease = Buffers.List.Get( out List result ); for (int i = 0; i < methods.Length; i++) { MethodInfo method = methods[i]; if (HasAttributeSafe(method, inherit)) { result.Add(method); } } return result.ToArray(); } catch { return Array.Empty(); } } public static PropertyInfo[] GetPropertiesWithAttributeSafe( this Type type, bool inherit = true ) where TAttribute : Attribute { if (type == null) { return Array.Empty(); } try { PropertyInfo[] properties = type.GetProperties( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static ); using PooledResource> lease = Buffers.List.Get( out List result ); for (int i = 0; i < properties.Length; i++) { PropertyInfo property = properties[i]; if (HasAttributeSafe(property, inherit)) { result.Add(property); } } return result.ToArray(); } catch { return Array.Empty(); } } public static FieldInfo[] GetFieldsWithAttributeSafe( this Type type, bool inherit = true ) where TAttribute : Attribute { if (type == null) { return Array.Empty(); } try { FieldInfo[] fields = type.GetFields( BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static ); using PooledResource> lease = Buffers.List.Get( out List result ); for (int i = 0; i < fields.Length; i++) { FieldInfo field = fields[i]; if (HasAttributeSafe(field, inherit)) { result.Add(field); } } return result.ToArray(); } catch { return Array.Empty(); } } /// /// Checks if a type has any field decorated with the specified attribute type. /// Short-circuits on first match for efficiency. /// /// The attribute type to search for. /// The type to inspect. /// Whether to search the attribute's inheritance chain. /// True if any field has the attribute; otherwise false. public static bool HasAnyFieldWithAttribute(this Type type, bool inherit = true) where TAttribute : Attribute { if (type == null) { return false; } FieldInfo[] fields = GetFieldsCached(type, AllInstanceFieldsFlags); for (int i = 0; i < fields.Length; i++) { if (HasAttributeSafe(fields[i], inherit)) { return true; } } return false; } /// /// Checks if a type has any field decorated with any of the specified attribute types. /// Short-circuits on first match for efficiency. Useful when checking for multiple /// related attributes without allocating enumerators. /// /// The type to inspect. /// The attribute types to search for. /// Whether to search the attribute's inheritance chain. /// True if any field has any of the attributes; otherwise false. public static bool HasAnyFieldWithAttributes( this Type type, Type[] attributeTypes, bool inherit = true ) { if (type == null || attributeTypes == null || attributeTypes.Length == 0) { return false; } FieldInfo[] fields = GetFieldsCached(type, AllInstanceFieldsFlags); for (int i = 0; i < fields.Length; i++) { FieldInfo field = fields[i]; if (field == null) { continue; } for (int j = 0; j < attributeTypes.Length; j++) { Type attributeType = attributeTypes[j]; if (attributeType != null && HasAttributeSafe(field, attributeType, inherit)) { return true; } } } return false; } private static bool CheckDynamicIlSupport() { #if !EMIT_DYNAMIC_IL return false; #else try { DynamicMethod dynamicMethod = new( "UnityHelpersIlProbe", typeof(int), Type.EmptyTypes, typeof(ReflectionHelpers), true ); ILGenerator il = dynamicMethod.GetILGenerator(); il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ret); _ = ((Func)dynamicMethod.CreateDelegate(typeof(Func)))(); return true; } catch { return false; } #endif } #if EMIT_DYNAMIC_IL private static Func BuildMethodInvokerIL(MethodInfo method) { try { DynamicMethod dynamicMethod = new( $"Invoke{method.DeclaringType.Name}_{method.Name}", typeof(object), new[] { typeof(object), typeof(object[]) }, method.DeclaringType, true ); ILGenerator il = dynamicMethod.GetILGenerator(); ParameterInfo[] parameters = method.GetParameters(); il.Emit(OpCodes.Ldarg_0); il.Emit( method.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, method.DeclaringType ); for (int i = 0; i < parameters.Length; i++) { il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ldelem_Ref); Type paramType = parameters[i].ParameterType; if (paramType.IsValueType) { il.Emit(OpCodes.Unbox_Any, paramType); } else { il.Emit(OpCodes.Castclass, paramType); } } il.Emit(method.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt, method); if (method.ReturnType == typeof(void)) { il.Emit(OpCodes.Ldnull); } else if (method.ReturnType.IsValueType) { il.Emit(OpCodes.Box, method.ReturnType); } il.Emit(OpCodes.Ret); return (Func) dynamicMethod.CreateDelegate(typeof(Func)); } catch { return null; } } private static Func BuildStaticMethodInvokerIL(MethodInfo method) { try { DynamicMethod dynamicMethod = new( $"InvokeStatic{method.DeclaringType.Name}_{method.Name}", typeof(object), new[] { typeof(object[]) }, method.DeclaringType, true ); ILGenerator il = dynamicMethod.GetILGenerator(); ParameterInfo[] parameters = method.GetParameters(); for (int i = 0; i < parameters.Length; i++) { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ldelem_Ref); Type paramType = parameters[i].ParameterType; if (paramType.IsValueType) { il.Emit(OpCodes.Unbox_Any, paramType); } else { il.Emit(OpCodes.Castclass, paramType); } } il.Emit(OpCodes.Call, method); if (method.ReturnType == typeof(void)) { il.Emit(OpCodes.Ldnull); } else if (method.ReturnType.IsValueType) { il.Emit(OpCodes.Box, method.ReturnType); } il.Emit(OpCodes.Ret); return (Func) dynamicMethod.CreateDelegate(typeof(Func)); } catch { return null; } } private static Func BuildConstructorIL(ConstructorInfo constructor) { try { DynamicMethod dynamicMethod = new( $"Create{constructor.DeclaringType.Name}", typeof(object), new[] { typeof(object[]) }, constructor.DeclaringType, true ); ILGenerator il = dynamicMethod.GetILGenerator(); ParameterInfo[] parameters = constructor.GetParameters(); for (int i = 0; i < parameters.Length; i++) { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ldelem_Ref); Type paramType = parameters[i].ParameterType; if (paramType.IsValueType) { il.Emit(OpCodes.Unbox_Any, paramType); } else { il.Emit(OpCodes.Castclass, paramType); } } il.Emit(OpCodes.Newobj, constructor); if (constructor.DeclaringType.IsValueType) { il.Emit(OpCodes.Box, constructor.DeclaringType); } il.Emit(OpCodes.Ret); return (Func) dynamicMethod.CreateDelegate(typeof(Func)); } catch { return null; } } #endif private static bool CheckExpressionCompilationSupport() { #if !SUPPORT_EXPRESSION_COMPILE return false; #else try { // Test if expression compilation works by trying a simple lambda Expression> testExpr = () => 42; Func compiled = testExpr.Compile(); return compiled() == 42; } catch { return false; } #endif } private static Action CreateCompiledHashSetAdder( Type hashSetType, Type elementType, MethodInfo addMethod ) { if (!ExpressionsEnabled) { return null; } try { ParameterExpression setParam = Expression.Parameter(typeof(object), "hashSet"); ParameterExpression valueParam = Expression.Parameter(typeof(object), "value"); Expression castSet = Expression.Convert(setParam, hashSetType); Expression castValue = Expression.Convert(valueParam, elementType); MethodCallExpression call = Expression.Call(castSet, addMethod, castValue); Expression body = addMethod.ReturnType == typeof(void) ? call : Expression.Block(call, Expression.Empty()); return Expression .Lambda>(body, setParam, valueParam) .Compile(); } catch { return null; } } private static Func CreateCompiledMethodInvoker(MethodInfo method) { if (!ExpressionsEnabled) { return CreateDelegateMethodInvoker(method) ?? ((instance, args) => method.Invoke(instance, args)); } try { ParameterExpression instanceParam = Expression.Parameter( typeof(object), "instance" ); ParameterExpression argsParam = Expression.Parameter(typeof(object[]), "args"); Expression instanceExpression = method.DeclaringType.IsValueType ? Expression.Unbox(instanceParam, method.DeclaringType) : Expression.Convert(instanceParam, method.DeclaringType); ParameterInfo[] parameters = method.GetParameters(); Expression[] paramExpressions = new Expression[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { Expression argExpression = Expression.ArrayIndex( argsParam, Expression.Constant(i) ); Type paramType = parameters[i].ParameterType; paramExpressions[i] = paramType.IsValueType ? Expression.Unbox(argExpression, paramType) : Expression.Convert(argExpression, paramType); } Expression callExpression = Expression.Call( instanceExpression, method, paramExpressions ); Expression returnExpression = method.ReturnType == typeof(void) ? Expression.Block(callExpression, Expression.Constant(null)) : method.ReturnType.IsValueType ? Expression.Convert(callExpression, typeof(object)) : callExpression; return Expression .Lambda>( returnExpression, instanceParam, argsParam ) .Compile(); } catch { return (instance, args) => method.Invoke(instance, args); } } private static Func CreateCompiledStaticMethodInvoker(MethodInfo method) { if (!ExpressionsEnabled) { return CreateDelegateStaticMethodInvoker(method) ?? (args => method.Invoke(null, args)); } try { ParameterExpression argsParam = Expression.Parameter(typeof(object[]), "args"); ParameterInfo[] parameters = method.GetParameters(); Expression[] paramExpressions = new Expression[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { Expression argExpression = Expression.ArrayIndex( argsParam, Expression.Constant(i) ); Type paramType = parameters[i].ParameterType; paramExpressions[i] = paramType.IsValueType ? Expression.Unbox(argExpression, paramType) : Expression.Convert(argExpression, paramType); } Expression callExpression = Expression.Call(method, paramExpressions); Expression returnExpression = method.ReturnType == typeof(void) ? Expression.Block(callExpression, Expression.Constant(null)) : method.ReturnType.IsValueType ? Expression.Convert(callExpression, typeof(object)) : callExpression; return Expression .Lambda>(returnExpression, argsParam) .Compile(); } catch { return args => method.Invoke(null, args); } } private static Func CreateCompiledConstructor(ConstructorInfo constructor) { if (!ExpressionsEnabled) { return CreateDelegateConstructor(constructor) ?? (args => constructor.Invoke(args)); } try { ParameterExpression argsParam = Expression.Parameter(typeof(object[]), "args"); ParameterInfo[] parameters = constructor.GetParameters(); Expression[] paramExpressions = new Expression[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { Expression argExpression = Expression.ArrayIndex( argsParam, Expression.Constant(i) ); Type paramType = parameters[i].ParameterType; paramExpressions[i] = paramType.IsValueType ? Expression.Unbox(argExpression, paramType) : Expression.Convert(argExpression, paramType); } Expression newExpression = Expression.New(constructor, paramExpressions); Expression returnExpression = constructor.DeclaringType.IsValueType ? Expression.Convert(newExpression, typeof(object)) : newExpression; return Expression .Lambda>(returnExpression, argsParam) .Compile(); } catch { return args => constructor.Invoke(args); } } private static Func CreateCompiledParameterlessConstructor( ConstructorInfo constructor ) { if (!ExpressionsEnabled) { return CreateDelegateParameterlessConstructor(constructor) ?? (() => constructor.Invoke(null)); } try { Expression newExpression = Expression.New(constructor); Expression body = constructor.DeclaringType.IsValueType ? Expression.Convert(newExpression, typeof(object)) : newExpression; return Expression.Lambda>(body).Compile(); } catch { return CreateDelegateParameterlessConstructor(constructor) ?? (() => constructor.Invoke(null)); } } private static Func CreateCompiledParameterlessConstructor( ConstructorInfo constructor, Type constructedType ) { if (!ExpressionsEnabled) { if (constructedType == typeof(T)) { return CreateDelegateParameterlessConstructor(constructor) ?? (() => (T)constructor.Invoke(null)); } return () => (T)constructor.Invoke(null); } try { Expression newExpression = Expression.New(constructor); Expression body = constructedType.IsValueType && typeof(T) != constructedType ? Expression.Convert(newExpression, typeof(T)) : constructedType == typeof(T) ? newExpression : Expression.Convert(newExpression, typeof(T)); return Expression.Lambda>(body).Compile(); } catch { return () => (T)constructor.Invoke(null); } } private static Func CreateCompiledIndexerGetter( PropertyInfo property ) { if (!ExpressionsEnabled) { return null; } try { ParameterExpression instanceParam = Expression.Parameter( typeof(object), "instance" ); ParameterExpression argsParam = Expression.Parameter(typeof(object[]), "args"); MethodInfo getMethod = property.GetGetMethod(true); if (getMethod == null) { return null; } Expression targetExpression = property.DeclaringType.IsValueType ? Expression.Unbox(instanceParam, property.DeclaringType) : Expression.Convert(instanceParam, property.DeclaringType); ParameterInfo[] indices = property.GetIndexParameters(); Expression[] indexExpressions = new Expression[indices.Length]; for (int i = 0; i < indices.Length; i++) { Expression element = Expression.ArrayIndex(argsParam, Expression.Constant(i)); Type indexType = indices[i].ParameterType; indexExpressions[i] = indexType.IsValueType ? Expression.Unbox(element, indexType) : Expression.Convert(element, indexType); } Expression propertyExpression = getMethod.IsStatic ? Expression.Property(null, property, indexExpressions) : Expression.Property(targetExpression, property, indexExpressions); Expression body = property.PropertyType.IsValueType ? Expression.Convert(propertyExpression, typeof(object)) : propertyExpression; return Expression .Lambda>(body, instanceParam, argsParam) .Compile(); } catch { return null; } } private static Action CreateCompiledIndexerSetter( PropertyInfo property ) { if (!ExpressionsEnabled) { return null; } try { MethodInfo setMethod = property.GetSetMethod(true); if (setMethod == null) { return null; } ParameterExpression instanceParam = Expression.Parameter( typeof(object), "instance" ); ParameterExpression valueParam = Expression.Parameter(typeof(object), "value"); ParameterExpression argsParam = Expression.Parameter(typeof(object[]), "args"); Expression targetExpression = property.DeclaringType.IsValueType ? Expression.Unbox(instanceParam, property.DeclaringType) : Expression.Convert(instanceParam, property.DeclaringType); ParameterInfo[] indices = property.GetIndexParameters(); Expression[] indexExpressions = new Expression[indices.Length]; for (int i = 0; i < indices.Length; i++) { Expression element = Expression.ArrayIndex(argsParam, Expression.Constant(i)); Type indexType = indices[i].ParameterType; indexExpressions[i] = indexType.IsValueType ? Expression.Unbox(element, indexType) : Expression.Convert(element, indexType); } Expression valueExpression = property.PropertyType.IsValueType ? Expression.Unbox(valueParam, property.PropertyType) : Expression.Convert(valueParam, property.PropertyType); Expression[] arguments = new Expression[indexExpressions.Length + 1]; for (int i = 0; i < indexExpressions.Length; i++) { arguments[i] = indexExpressions[i]; } arguments[indexExpressions.Length] = valueExpression; Expression callExpression = setMethod.IsStatic ? Expression.Call(setMethod, arguments) : Expression.Call(targetExpression, setMethod, arguments); return Expression .Lambda>( callExpression, instanceParam, valueParam, argsParam ) .Compile(); } catch { return null; } } private static Func CreateCompiledParameterlessConstructor( ConstructorInfo constructor ) { return CreateCompiledParameterlessConstructor( constructor, constructor.DeclaringType ); } private static Func CreateCompiledFieldGetter(FieldInfo field) { try { ParameterExpression instanceParam = Expression.Parameter( typeof(object), "instance" ); Expression instanceExpression = field.IsStatic ? null : field.DeclaringType.IsValueType ? Expression.Unbox(instanceParam, field.DeclaringType) : Expression.Convert(instanceParam, field.DeclaringType); Expression fieldExpression = field.IsStatic ? Expression.Field(null, field) : Expression.Field(instanceExpression, field); Expression returnExpression = field.FieldType.IsValueType ? Expression.Convert(fieldExpression, typeof(object)) : fieldExpression; return Expression .Lambda>(returnExpression, instanceParam) .Compile(); } catch { return null; } } private static bool CanInlineAssignment(Type sourceType, Type targetType) { if (sourceType == targetType) { return true; } if (!targetType.IsValueType) { if (sourceType.IsValueType) { return true; } return targetType.IsAssignableFrom(sourceType); } if (!sourceType.IsValueType) { return sourceType == typeof(object); } return false; } private static bool CanInlineReturnConversion(Type actualType, Type requestedType) { if (actualType == requestedType) { return true; } if (requestedType.IsValueType) { if (!actualType.IsValueType) { return actualType == typeof(object); } return false; } if (actualType.IsValueType) { return true; } return requestedType.IsAssignableFrom(actualType); } private static Func CreateCompiledPropertyGetter(PropertyInfo property) { try { MethodInfo getMethod = property.GetGetMethod(true); if (getMethod == null) { return property.GetValue; } ParameterExpression instanceParam = Expression.Parameter( typeof(object), "instance" ); Expression propertyExpression; if (getMethod.IsStatic) { propertyExpression = Expression.Property(null, property); } else { Expression instanceExpression = property.DeclaringType.IsValueType ? Expression.Unbox(instanceParam, property.DeclaringType) : Expression.Convert(instanceParam, property.DeclaringType); propertyExpression = Expression.Property(instanceExpression, property); } Expression returnExpression = property.PropertyType.IsValueType ? Expression.Convert(propertyExpression, typeof(object)) : propertyExpression; return Expression .Lambda>(returnExpression, instanceParam) .Compile(); } catch { return property.GetValue; } } private static Action CreateCompiledPropertySetter(PropertyInfo property) { if (!ExpressionsEnabled) { return property.SetValue; } try { MethodInfo setMethod = property.GetSetMethod(true); if (setMethod == null) { return property.SetValue; } ParameterExpression instanceParam = Expression.Parameter( typeof(object), "instance" ); ParameterExpression valueParam = Expression.Parameter(typeof(object), "value"); Expression valueExpression = property.PropertyType.IsValueType ? Expression.Unbox(valueParam, property.PropertyType) : Expression.Convert(valueParam, property.PropertyType); Expression callExpression; if (setMethod.IsStatic) { callExpression = Expression.Call(setMethod, valueExpression); } else { Expression instanceExpression = property.DeclaringType.IsValueType ? Expression.Unbox(instanceParam, property.DeclaringType) : Expression.Convert(instanceParam, property.DeclaringType); callExpression = Expression.Call( instanceExpression, setMethod, valueExpression ); } return Expression .Lambda>(callExpression, instanceParam, valueParam) .Compile(); } catch { return property.SetValue; } } private static Func CreateCompiledTypedFieldGetter( FieldInfo field ) { if (!ExpressionsEnabled) { return null; } try { ParameterExpression instanceParam = Expression.Parameter( typeof(TInstance), "instance" ); Expression fieldExpression; if (field.IsStatic) { fieldExpression = Expression.Field(null, field); } else { Expression instanceExpression = PrepareInstanceExpression( instanceParam, field.DeclaringType ); fieldExpression = Expression.Field(instanceExpression, field); } Expression body = field.FieldType == typeof(TValue) ? fieldExpression : Expression.Convert(fieldExpression, typeof(TValue)); return Expression.Lambda>(body, instanceParam).Compile(); } catch { return null; } } private static FieldSetter CreateCompiledTypedFieldSetter< TInstance, TValue >(FieldInfo field) { if (!ExpressionsEnabled) { return null; } if (!field.IsStatic && typeof(TInstance) != field.DeclaringType) { return null; } try { ParameterExpression instanceParam = Expression.Parameter( typeof(TInstance).MakeByRefType(), "instance" ); ParameterExpression valueParam = Expression.Parameter(typeof(TValue), "value"); Expression valueExpression = field.FieldType == typeof(TValue) ? valueParam : Expression.Convert(valueParam, field.FieldType); Expression assignExpression; if (field.IsStatic) { assignExpression = Expression.Assign( Expression.Field(null, field), valueExpression ); } else { Expression fieldAccess = Expression.Field(instanceParam, field); assignExpression = Expression.Assign(fieldAccess, valueExpression); } return Expression .Lambda>( assignExpression, instanceParam, valueParam ) .Compile(); } catch { return null; } } private static Func CreateCompiledTypedStaticFieldGetter(FieldInfo field) { if (!ExpressionsEnabled) { return null; } try { Expression body = Expression.Field(null, field); if (field.FieldType != typeof(TValue)) { body = Expression.Convert(body, typeof(TValue)); } return Expression.Lambda>(body).Compile(); } catch { return null; } } private static Action CreateCompiledTypedStaticFieldSetter(FieldInfo field) { if (!ExpressionsEnabled) { return null; } try { ParameterExpression valueParam = Expression.Parameter(typeof(TValue), "value"); Expression valueExpression = field.FieldType == typeof(TValue) ? valueParam : Expression.Convert(valueParam, field.FieldType); Expression assignExpression = Expression.Assign( Expression.Field(null, field), valueExpression ); return Expression.Lambda>(assignExpression, valueParam).Compile(); } catch { return null; } } private static Func CreateCompiledTypedPropertyGetter( PropertyInfo property, MethodInfo getMethod ) { if (!ExpressionsEnabled) { return null; } try { ParameterExpression instanceParam = Expression.Parameter( typeof(TInstance), "instance" ); Expression callExpression; if (getMethod.IsStatic) { callExpression = Expression.Call(getMethod); } else { Expression instanceExpression = PrepareInstanceExpression( instanceParam, property.DeclaringType ); callExpression = Expression.Call(instanceExpression, getMethod); } Expression body = property.PropertyType == typeof(TValue) ? callExpression : Expression.Convert(callExpression, typeof(TValue)); return Expression.Lambda>(body, instanceParam).Compile(); } catch { return null; } } private static Action CreateCompiledTypedPropertySetter< TInstance, TValue >(PropertyInfo property, MethodInfo setMethod) { if (!ExpressionsEnabled) { return null; } if (!setMethod.IsStatic && property.DeclaringType.IsValueType) { return null; } try { ParameterExpression instanceParam = Expression.Parameter( typeof(TInstance), "instance" ); ParameterExpression valueParam = Expression.Parameter(typeof(TValue), "value"); Expression valueExpression = property.PropertyType == typeof(TValue) ? valueParam : Expression.Convert(valueParam, property.PropertyType); MethodCallExpression callExpression; if (setMethod.IsStatic) { callExpression = Expression.Call(setMethod, valueExpression); } else { Expression instanceExpression = PrepareInstanceExpression( instanceParam, property.DeclaringType ); callExpression = Expression.Call( instanceExpression, setMethod, valueExpression ); } return Expression .Lambda>(callExpression, instanceParam, valueParam) .Compile(); } catch { return null; } } private static Func CreateCompiledTypedStaticPropertyGetter( PropertyInfo property, MethodInfo getMethod ) { if (!ExpressionsEnabled) { return null; } try { Expression body = Expression.Call(getMethod); if (property.PropertyType != typeof(TValue)) { body = Expression.Convert(body, typeof(TValue)); } return Expression.Lambda>(body).Compile(); } catch { return null; } } private static Action CreateCompiledTypedStaticPropertySetter( PropertyInfo property, MethodInfo setMethod ) { if (!ExpressionsEnabled) { return null; } try { ParameterExpression valueParam = Expression.Parameter(typeof(TValue), "value"); Expression valueExpression = property.PropertyType == typeof(TValue) ? valueParam : Expression.Convert(valueParam, property.PropertyType); MethodCallExpression callExpression = Expression.Call(setMethod, valueExpression); return Expression.Lambda>(callExpression, valueParam).Compile(); } catch { return null; } } private static Expression PrepareInstanceExpression( ParameterExpression instanceParameter, Type declaringType ) { if (instanceParameter.Type == declaringType) { return instanceParameter; } return Expression.Convert(instanceParameter, declaringType); } #if EMIT_DYNAMIC_IL private static void EmitAssignmentConversion( ILGenerator il, Type sourceType, Type targetType ) { if (targetType == sourceType) { return; } if (targetType.IsValueType) { if (!sourceType.IsValueType) { il.Emit(OpCodes.Unbox_Any, targetType); } } else { if (sourceType.IsValueType) { il.Emit(OpCodes.Box, sourceType); if (targetType != typeof(object)) { il.Emit(OpCodes.Castclass, targetType); } } else if (!targetType.IsAssignableFrom(sourceType)) { il.Emit(OpCodes.Castclass, targetType); } } } private static void EmitReturnConversion( ILGenerator il, Type actualType, Type requestedType ) { if (requestedType == actualType) { return; } if (requestedType.IsValueType) { if (!actualType.IsValueType) { il.Emit(OpCodes.Unbox_Any, requestedType); } } else { if (actualType.IsValueType) { il.Emit(OpCodes.Box, actualType); if (requestedType != typeof(object)) { il.Emit(OpCodes.Castclass, requestedType); } } else if (!requestedType.IsAssignableFrom(actualType)) { il.Emit(OpCodes.Castclass, requestedType); } } } private static Func BuildParameterlessConstructorIL(ConstructorInfo constructor) { DynamicMethod dynamicMethod = new( $"New_{constructor.DeclaringType.Name}_Obj", typeof(object), Type.EmptyTypes, constructor.DeclaringType, true ); ILGenerator il = dynamicMethod.GetILGenerator(); il.Emit(OpCodes.Newobj, constructor); if (constructor.DeclaringType.IsValueType) { il.Emit(OpCodes.Box, constructor.DeclaringType); } il.Emit(OpCodes.Ret); return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } private static Func BuildTypedParameterlessConstructorIL(ConstructorInfo constructor) { DynamicMethod dynamicMethod = new( $"New_{constructor.DeclaringType.Name}_{typeof(T).Name}", typeof(T), Type.EmptyTypes, constructor.DeclaringType, true ); ILGenerator il = dynamicMethod.GetILGenerator(); il.Emit(OpCodes.Newobj, constructor); Type declaringType = constructor.DeclaringType; if (declaringType != typeof(T)) { if (declaringType.IsValueType) { il.Emit(OpCodes.Box, declaringType); if (typeof(T) != typeof(object)) { il.Emit(OpCodes.Castclass, typeof(T)); } } else if (!typeof(T).IsAssignableFrom(declaringType)) { il.Emit(OpCodes.Castclass, typeof(T)); } } il.Emit(OpCodes.Ret); return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } private static Func BuildIndexerGetterIL(PropertyInfo property) { MethodInfo getter = property.GetGetMethod(true) ?? throw new ArgumentException("Indexer has no getter", nameof(property)); DynamicMethod dynamicMethod = new( $"GetIndexer_{property.DeclaringType.Name}_{property.Name}", typeof(object), new[] { typeof(object), typeof(object[]) }, property.DeclaringType, true ); ILGenerator il = dynamicMethod.GetILGenerator(); bool isStatic = getter.IsStatic; if (!isStatic) { il.Emit(OpCodes.Ldarg_0); il.Emit( property.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, property.DeclaringType ); } ParameterInfo[] indices = property.GetIndexParameters(); for (int i = 0; i < indices.Length; i++) { il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ldelem_Ref); EmitAssignmentConversion(il, typeof(object), indices[i].ParameterType); } il.Emit( getter.IsStatic ? OpCodes.Call : property.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt, getter ); EmitReturnConversion(il, property.PropertyType, typeof(object)); il.Emit(OpCodes.Ret); return (Func) dynamicMethod.CreateDelegate(typeof(Func)); } private static Action BuildIndexerSetterIL(PropertyInfo property) { MethodInfo setter = property.GetSetMethod(true) ?? throw new ArgumentException("Indexer has no setter", nameof(property)); DynamicMethod dynamicMethod = new( $"SetIndexer_{property.DeclaringType.Name}_{property.Name}", typeof(void), new[] { typeof(object), typeof(object), typeof(object[]) }, property.DeclaringType, true ); ILGenerator il = dynamicMethod.GetILGenerator(); bool isStatic = setter.IsStatic; if (!isStatic) { il.Emit(OpCodes.Ldarg_0); il.Emit( property.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, property.DeclaringType ); } ParameterInfo[] indices = property.GetIndexParameters(); for (int i = 0; i < indices.Length; i++) { il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldc_I4, i); il.Emit(OpCodes.Ldelem_Ref); EmitAssignmentConversion(il, typeof(object), indices[i].ParameterType); } il.Emit(OpCodes.Ldarg_1); EmitAssignmentConversion(il, typeof(object), property.PropertyType); il.Emit( setter.IsStatic ? OpCodes.Call : property.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt, setter ); il.Emit(OpCodes.Ret); return (Action) dynamicMethod.CreateDelegate(typeof(Action)); } private static Func BuildTypedFieldGetterIL( FieldInfo field ) { DynamicMethod dynamicMethod = new( $"GetGeneric{field.DeclaringType.Name}_{field.Name}", typeof(TValue), new[] { typeof(TInstance) }, field.DeclaringType, true ); ILGenerator il = dynamicMethod.GetILGenerator(); if (field.IsStatic) { il.Emit(OpCodes.Ldsfld, field); } else { if (typeof(TInstance).IsValueType) { il.Emit(OpCodes.Ldarga_S, 0); } else { il.Emit(OpCodes.Ldarg_0); } if (field.DeclaringType != typeof(TInstance)) { il.Emit( field.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, field.DeclaringType ); } il.Emit(OpCodes.Ldfld, field); } EmitReturnConversion(il, field.FieldType, typeof(TValue)); il.Emit(OpCodes.Ret); return (Func) dynamicMethod.CreateDelegate(typeof(Func)); } private static FieldSetter BuildTypedFieldSetterIL( FieldInfo field ) { DynamicMethod dynamicMethod = new( $"SetFieldGeneric{field.DeclaringType.Name}_{field.Name}", typeof(void), new[] { typeof(TInstance).MakeByRefType(), typeof(TValue) }, field.Module, true ); ILGenerator il = dynamicMethod.GetILGenerator(); if (field.IsStatic) { il.Emit(OpCodes.Ldarg_1); EmitAssignmentConversion(il, typeof(TValue), field.FieldType); il.Emit(OpCodes.Stsfld, field); } else { if (typeof(TInstance).IsValueType) { il.Emit(OpCodes.Ldarg_0); } else { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldind_Ref); } if (field.DeclaringType != typeof(TInstance)) { il.Emit( field.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, field.DeclaringType ); } il.Emit(OpCodes.Ldarg_1); EmitAssignmentConversion(il, typeof(TValue), field.FieldType); il.Emit(OpCodes.Stfld, field); } il.Emit(OpCodes.Ret); return (FieldSetter) dynamicMethod.CreateDelegate(typeof(FieldSetter)); } private static Func BuildTypedStaticFieldGetterIL(FieldInfo field) { DynamicMethod dynamicMethod = new( $"GetStaticTyped{field.DeclaringType.Name}_{field.Name}", typeof(TValue), Type.EmptyTypes, field.DeclaringType.Module, true ); ILGenerator il = dynamicMethod.GetILGenerator(); il.Emit(OpCodes.Ldsfld, field); EmitReturnConversion(il, field.FieldType, typeof(TValue)); il.Emit(OpCodes.Ret); return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } private static Action BuildTypedStaticFieldSetterIL(FieldInfo field) { DynamicMethod dynamicMethod = new( $"SetStaticTyped{field.DeclaringType.Name}_{field.Name}", typeof(void), new[] { typeof(TValue) }, field.Module, true ); ILGenerator il = dynamicMethod.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); EmitAssignmentConversion(il, typeof(TValue), field.FieldType); il.Emit(OpCodes.Stsfld, field); il.Emit(OpCodes.Ret); return (Action)dynamicMethod.CreateDelegate(typeof(Action)); } private static Func BuildTypedPropertyGetterIL( PropertyInfo property, MethodInfo getMethod ) { DynamicMethod dynamicMethod = new( $"GetGeneric{property.DeclaringType.Name}_{property.Name}", typeof(TValue), new[] { typeof(TInstance) }, property.DeclaringType, true ); ILGenerator il = dynamicMethod.GetILGenerator(); if (getMethod.IsStatic) { il.Emit(OpCodes.Call, getMethod); } else { if (typeof(TInstance).IsValueType) { il.Emit(OpCodes.Ldarga_S, 0); } else { il.Emit(OpCodes.Ldarg_0); } if (property.DeclaringType != typeof(TInstance)) { il.Emit( property.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, property.DeclaringType ); } il.Emit( property.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt, getMethod ); } EmitReturnConversion(il, property.PropertyType, typeof(TValue)); il.Emit(OpCodes.Ret); return (Func) dynamicMethod.CreateDelegate(typeof(Func)); } private static Action BuildTypedPropertySetterIL( PropertyInfo property, MethodInfo setMethod ) { DynamicMethod dynamicMethod = new( $"SetPropertyGeneric{property.DeclaringType.Name}_{property.Name}", typeof(void), new[] { typeof(TInstance), typeof(TValue) }, property.DeclaringType, true ); ILGenerator il = dynamicMethod.GetILGenerator(); if (setMethod.IsStatic) { il.Emit(OpCodes.Ldarg_1); EmitAssignmentConversion(il, typeof(TValue), property.PropertyType); il.Emit(OpCodes.Call, setMethod); } else { if (typeof(TInstance).IsValueType) { il.Emit(OpCodes.Ldarga_S, 0); } else { il.Emit(OpCodes.Ldarg_0); } if (property.DeclaringType != typeof(TInstance)) { il.Emit( property.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass, property.DeclaringType ); } il.Emit(OpCodes.Ldarg_1); EmitAssignmentConversion(il, typeof(TValue), property.PropertyType); il.Emit( property.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt, setMethod ); } il.Emit(OpCodes.Ret); return (Action) dynamicMethod.CreateDelegate(typeof(Action)); } private static Func BuildTypedStaticPropertyGetterIL( PropertyInfo property, MethodInfo getMethod ) { DynamicMethod dynamicMethod = new( $"GetStaticTyped{property.DeclaringType.Name}_{property.Name}", typeof(TValue), Type.EmptyTypes, property.DeclaringType, true ); ILGenerator il = dynamicMethod.GetILGenerator(); il.Emit(OpCodes.Call, getMethod); EmitReturnConversion(il, property.PropertyType, typeof(TValue)); il.Emit(OpCodes.Ret); return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } private static Action BuildTypedStaticPropertySetterIL( PropertyInfo property, MethodInfo setMethod ) { DynamicMethod dynamicMethod = new( $"SetStaticTyped{property.DeclaringType.Name}_{property.Name}", typeof(void), new[] { typeof(TValue) }, property.DeclaringType, true ); ILGenerator il = dynamicMethod.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); EmitAssignmentConversion(il, typeof(TValue), property.PropertyType); il.Emit(OpCodes.Call, setMethod); il.Emit(OpCodes.Ret); return (Action)dynamicMethod.CreateDelegate(typeof(Action)); } #endif private static Func CreateCompiledStaticFieldGetter(FieldInfo field) { if (!ExpressionsEnabled) { return null; } try { Expression fieldExpression = Expression.Field(null, field); Expression returnExpression = field.FieldType.IsValueType ? Expression.Convert(fieldExpression, typeof(object)) : fieldExpression; return Expression.Lambda>(returnExpression).Compile(); } catch { return null; } } private static Action CreateCompiledFieldSetter(FieldInfo field) { if (!ExpressionsEnabled) { return field.SetValue; } try { ParameterExpression instanceParam = Expression.Parameter( typeof(object), "instance" ); ParameterExpression valueParam = Expression.Parameter(typeof(object), "value"); Expression instanceExpression = field.DeclaringType.IsValueType ? Expression.Unbox(instanceParam, field.DeclaringType) : Expression.Convert(instanceParam, field.DeclaringType); Expression valueExpression = field.FieldType.IsValueType ? Expression.Unbox(valueParam, field.FieldType) : Expression.Convert(valueParam, field.FieldType); Expression assignExpression = Expression.Assign( Expression.Field(instanceExpression, field), valueExpression ); return Expression .Lambda>(assignExpression, instanceParam, valueParam) .Compile(); } catch { return field.SetValue; } } private static Action CreateCompiledStaticFieldSetter(FieldInfo field) { if (!ExpressionsEnabled) { return null; } try { ParameterExpression valueParam = Expression.Parameter(typeof(object), "value"); Expression valueExpression = field.FieldType.IsValueType ? Expression.Unbox(valueParam, field.FieldType) : Expression.Convert(valueParam, field.FieldType); Expression assignExpression = Expression.Assign( Expression.Field(null, field), valueExpression ); return Expression.Lambda>(assignExpression, valueParam).Compile(); } catch { return null; } } private static Func CreateDelegateMethodInvoker(MethodInfo method) { try { // For IL2CPP/WebGL, focus on simple optimizations that avoid DynamicInvoke // which can be slower than direct reflection in some cases ParameterInfo[] parameters = method.GetParameters(); // Only optimize very simple cases to avoid DynamicInvoke overhead if (parameters.Length == 0 && method.IsStatic) { if (method.ReturnType == typeof(void)) { Action staticAction = (Action) Delegate.CreateDelegate(typeof(Action), method); return (instance, args) => { staticAction(); return null; }; } if (method.ReturnType == typeof(int)) { Func staticFunc = (Func)Delegate.CreateDelegate(typeof(Func), method); return (instance, args) => staticFunc(); } if (method.ReturnType == typeof(string)) { Func staticFunc = (Func)Delegate.CreateDelegate(typeof(Func), method); return (instance, args) => staticFunc(); } if (method.ReturnType == typeof(bool)) { Func staticFunc = (Func)Delegate.CreateDelegate(typeof(Func), method); return (instance, args) => staticFunc(); } } // For most other cases, direct reflection is often faster than DynamicInvoke return null; } catch { return null; // Fallback to reflection } } private static Func CreateDelegateStaticMethodInvoker(MethodInfo method) { try { ParameterInfo[] parameters = method.GetParameters(); // Only optimize simple static methods with no parameters to avoid DynamicInvoke if (parameters.Length == 0) { if (method.ReturnType == typeof(void)) { Action action = (Action)Delegate.CreateDelegate(typeof(Action), method); return args => { action(); return null; }; } if (method.ReturnType == typeof(int)) { Func func = (Func)Delegate.CreateDelegate(typeof(Func), method); return args => func(); } if (method.ReturnType == typeof(string)) { Func func = (Func)Delegate.CreateDelegate(typeof(Func), method); return args => func(); } if (method.ReturnType == typeof(bool)) { Func func = (Func)Delegate.CreateDelegate(typeof(Func), method); return args => func(); } } // For other cases, reflection is often faster than DynamicInvoke return null; } catch { return null; } } private static Func CreateDelegateConstructor(ConstructorInfo constructor) { try { ParameterInfo[] parameters = constructor.GetParameters(); Type declaringType = constructor.DeclaringType; // For constructors, we can use Activator.CreateInstance with optimizations // or create wrapper delegates that call the constructor if (parameters.Length == 0) { // Use cached Activator.CreateInstance for parameterless constructors return args => Activator.CreateInstance(declaringType); } if (parameters.Length == 1) { Type paramType = parameters[0].ParameterType; return args => Activator.CreateInstance(declaringType, args[0]); } if (parameters.Length == 2) { return args => Activator.CreateInstance(declaringType, args[0], args[1]); } if (parameters.Length <= 4) { // For up to 4 parameters, use Activator.CreateInstance which is reasonably fast return args => Activator.CreateInstance(declaringType, args); } // For more complex constructors, fallback to reflection return null; } catch { return null; } } private static Func CreateDelegateParameterlessConstructor( ConstructorInfo constructor ) { try { // For parameterless constructors, we can use optimized Activator.CreateInstance if (constructor.GetParameters().Length == 0) { return () => (T)Activator.CreateInstance(typeof(T)); } return null; } catch { return null; } } private static Func CreateDelegateParameterlessConstructor( ConstructorInfo constructor ) { try { if (constructor.GetParameters().Length == 0) { return () => constructor.Invoke(null); } return null; } catch { return null; } } } }