com.wallstop-studios.unity-helpers 2.0.0-rc79.5 → 2.0.0-rc79.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,25 +1,44 @@
|
|
|
1
1
|
#if !((UNITY_WEBGL && !UNITY_EDITOR) || ENABLE_IL2CPP)
|
|
2
2
|
#define EMIT_DYNAMIC_IL
|
|
3
|
+
#define SUPPORT_EXPRESSION_COMPILE
|
|
3
4
|
#endif
|
|
4
5
|
|
|
5
6
|
namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
6
7
|
{
|
|
7
8
|
using System;
|
|
8
9
|
using System.Collections;
|
|
10
|
+
using System.Collections.Concurrent;
|
|
9
11
|
using System.Collections.Generic;
|
|
10
12
|
using System.Linq;
|
|
13
|
+
using System.Linq.Expressions;
|
|
11
14
|
using System.Reflection;
|
|
12
15
|
using System.Reflection.Emit;
|
|
13
16
|
using System.Runtime.CompilerServices;
|
|
14
|
-
using Extension;
|
|
15
17
|
|
|
16
18
|
public delegate void FieldSetter<TInstance, in TValue>(ref TInstance instance, TValue value);
|
|
17
19
|
|
|
18
20
|
public static class ReflectionHelpers
|
|
19
21
|
{
|
|
20
|
-
private static readonly
|
|
21
|
-
private static readonly
|
|
22
|
-
private static readonly
|
|
22
|
+
private static readonly ConcurrentDictionary<Type, Func<int, Array>> ArrayCreators = new();
|
|
23
|
+
private static readonly ConcurrentDictionary<Type, Func<IList>> ListCreators = new();
|
|
24
|
+
private static readonly ConcurrentDictionary<
|
|
25
|
+
Type,
|
|
26
|
+
Func<int, IList>
|
|
27
|
+
> ListWithCapacityCreators = new();
|
|
28
|
+
private static readonly ConcurrentDictionary<
|
|
29
|
+
MethodInfo,
|
|
30
|
+
Func<object, object[], object>
|
|
31
|
+
> MethodInvokers = new();
|
|
32
|
+
private static readonly ConcurrentDictionary<
|
|
33
|
+
MethodInfo,
|
|
34
|
+
Func<object[], object>
|
|
35
|
+
> StaticMethodInvokers = new();
|
|
36
|
+
private static readonly ConcurrentDictionary<
|
|
37
|
+
ConstructorInfo,
|
|
38
|
+
Func<object[], object>
|
|
39
|
+
> Constructors = new();
|
|
40
|
+
|
|
41
|
+
private static readonly bool CanCompileExpressions = CheckExpressionCompilationSupport();
|
|
23
42
|
|
|
24
43
|
public static bool IsAttributeDefined<T>(
|
|
25
44
|
this ICustomAttributeProvider provider,
|
|
@@ -30,10 +49,17 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
30
49
|
{
|
|
31
50
|
try
|
|
32
51
|
{
|
|
33
|
-
|
|
52
|
+
Type type = typeof(T);
|
|
53
|
+
if (provider.IsDefined(type, inherit))
|
|
34
54
|
{
|
|
35
|
-
|
|
36
|
-
|
|
55
|
+
object[] attributes = provider.GetCustomAttributes(type, inherit);
|
|
56
|
+
if (attributes.Length == 0)
|
|
57
|
+
{
|
|
58
|
+
attribute = default;
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
attribute = attributes[0] as T;
|
|
62
|
+
return attribute != null;
|
|
37
63
|
}
|
|
38
64
|
}
|
|
39
65
|
catch
|
|
@@ -96,7 +122,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
96
122
|
public static Func<object, object> GetFieldGetter(FieldInfo field)
|
|
97
123
|
{
|
|
98
124
|
#if !EMIT_DYNAMIC_IL
|
|
99
|
-
return field
|
|
125
|
+
return CreateCompiledFieldGetter(field);
|
|
100
126
|
#else
|
|
101
127
|
DynamicMethod dynamicMethod = new(
|
|
102
128
|
$"Get{field.DeclaringType.Name}_{field.Name}",
|
|
@@ -130,7 +156,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
130
156
|
public static Func<object, object> GetPropertyGetter(PropertyInfo property)
|
|
131
157
|
{
|
|
132
158
|
#if !EMIT_DYNAMIC_IL
|
|
133
|
-
return property
|
|
159
|
+
return CreateCompiledPropertyGetter(property);
|
|
134
160
|
#else
|
|
135
161
|
MethodInfo getMethod = property.GetGetMethod(true);
|
|
136
162
|
|
|
@@ -143,15 +169,25 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
143
169
|
);
|
|
144
170
|
|
|
145
171
|
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
172
|
+
|
|
173
|
+
if (getMethod.IsStatic)
|
|
174
|
+
{
|
|
175
|
+
// For static properties, don't load any arguments
|
|
176
|
+
il.Emit(OpCodes.Call, getMethod);
|
|
177
|
+
}
|
|
178
|
+
else
|
|
179
|
+
{
|
|
180
|
+
// For instance properties, load and cast the argument
|
|
181
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
182
|
+
il.Emit(
|
|
183
|
+
property.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
|
|
184
|
+
property.DeclaringType
|
|
185
|
+
);
|
|
186
|
+
il.Emit(
|
|
187
|
+
property.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt,
|
|
188
|
+
getMethod
|
|
189
|
+
);
|
|
190
|
+
}
|
|
155
191
|
|
|
156
192
|
if (property.PropertyType.IsValueType)
|
|
157
193
|
{
|
|
@@ -172,7 +208,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
172
208
|
}
|
|
173
209
|
|
|
174
210
|
#if !EMIT_DYNAMIC_IL
|
|
175
|
-
return (
|
|
211
|
+
return CreateCompiledStaticFieldGetter(field);
|
|
176
212
|
#else
|
|
177
213
|
DynamicMethod dynamicMethod = new(
|
|
178
214
|
$"Get{field.DeclaringType.Name}_{field.Name}",
|
|
@@ -279,7 +315,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
279
315
|
// Use null for instance, null for indexer args for static properties
|
|
280
316
|
return (TValue)property.GetValue(null, null);
|
|
281
317
|
}
|
|
282
|
-
#
|
|
318
|
+
#else
|
|
283
319
|
DynamicMethod dynamicMethod = new(
|
|
284
320
|
$"GetStatic_{property.DeclaringType.Name}_{property.Name}",
|
|
285
321
|
typeof(TValue),
|
|
@@ -316,6 +352,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
316
352
|
|
|
317
353
|
il.Emit(OpCodes.Ret);
|
|
318
354
|
return (Func<TValue>)dynamicMethod.CreateDelegate(typeof(Func<TValue>));
|
|
355
|
+
#endif
|
|
319
356
|
}
|
|
320
357
|
|
|
321
358
|
public static Func<TValue> GetStaticFieldGetter<TValue>(FieldInfo field)
|
|
@@ -446,7 +483,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
446
483
|
public static Action<object, object> GetFieldSetter(FieldInfo field)
|
|
447
484
|
{
|
|
448
485
|
#if !EMIT_DYNAMIC_IL
|
|
449
|
-
return field
|
|
486
|
+
return CreateCompiledFieldSetter(field);
|
|
450
487
|
#else
|
|
451
488
|
DynamicMethod dynamicMethod = new(
|
|
452
489
|
$"SetField{field.DeclaringType.Name}_{field.Name}",
|
|
@@ -483,7 +520,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
483
520
|
throw new ArgumentException(nameof(field));
|
|
484
521
|
}
|
|
485
522
|
#if !EMIT_DYNAMIC_IL
|
|
486
|
-
return
|
|
523
|
+
return CreateCompiledStaticFieldSetter(field);
|
|
487
524
|
#else
|
|
488
525
|
DynamicMethod dynamicMethod = new(
|
|
489
526
|
$"SetFieldStatic{field.DeclaringType.Name}_{field.Name}",
|
|
@@ -586,5 +623,1314 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
586
623
|
return (Func<int, IList>)dynamicMethod.CreateDelegate(typeof(Func<int, IList>));
|
|
587
624
|
#endif
|
|
588
625
|
}
|
|
626
|
+
|
|
627
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
628
|
+
public static object InvokeMethod(
|
|
629
|
+
MethodInfo method,
|
|
630
|
+
object instance,
|
|
631
|
+
params object[] parameters
|
|
632
|
+
)
|
|
633
|
+
{
|
|
634
|
+
return MethodInvokers
|
|
635
|
+
.GetOrAdd(method, methodInfo => GetMethodInvoker(methodInfo))
|
|
636
|
+
.Invoke(instance, parameters);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
640
|
+
public static object InvokeStaticMethod(MethodInfo method, params object[] parameters)
|
|
641
|
+
{
|
|
642
|
+
return StaticMethodInvokers
|
|
643
|
+
.GetOrAdd(method, methodInfo => GetStaticMethodInvoker(methodInfo))
|
|
644
|
+
.Invoke(parameters);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
648
|
+
public static object CreateInstance(ConstructorInfo constructor, params object[] parameters)
|
|
649
|
+
{
|
|
650
|
+
return Constructors
|
|
651
|
+
.GetOrAdd(constructor, ctor => GetConstructor(ctor))
|
|
652
|
+
.Invoke(parameters);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
656
|
+
public static T CreateInstance<T>(params object[] parameters)
|
|
657
|
+
{
|
|
658
|
+
Type type = typeof(T);
|
|
659
|
+
Type[] parameterTypes =
|
|
660
|
+
parameters?.Select(p => p?.GetType()).ToArray() ?? Type.EmptyTypes;
|
|
661
|
+
ConstructorInfo constructor = type.GetConstructor(parameterTypes);
|
|
662
|
+
if (constructor == null)
|
|
663
|
+
{
|
|
664
|
+
throw new ArgumentException($"No matching constructor found for type {type.Name}");
|
|
665
|
+
}
|
|
666
|
+
return (T)CreateInstance(constructor, parameters);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
670
|
+
public static T CreateGenericInstance<T>(
|
|
671
|
+
Type genericTypeDefinition,
|
|
672
|
+
Type[] genericArguments,
|
|
673
|
+
params object[] parameters
|
|
674
|
+
)
|
|
675
|
+
{
|
|
676
|
+
Type constructedType = genericTypeDefinition.MakeGenericType(genericArguments);
|
|
677
|
+
Type[] parameterTypes =
|
|
678
|
+
parameters?.Select(p => p?.GetType()).ToArray() ?? Type.EmptyTypes;
|
|
679
|
+
ConstructorInfo constructor = constructedType.GetConstructor(parameterTypes);
|
|
680
|
+
if (constructor == null)
|
|
681
|
+
{
|
|
682
|
+
throw new ArgumentException(
|
|
683
|
+
$"No matching constructor found for type {constructedType.Name}"
|
|
684
|
+
);
|
|
685
|
+
}
|
|
686
|
+
return (T)CreateInstance(constructor, parameters);
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
public static Func<object, object[], object> GetMethodInvoker(MethodInfo method)
|
|
690
|
+
{
|
|
691
|
+
if (method.IsStatic)
|
|
692
|
+
{
|
|
693
|
+
throw new ArgumentException(
|
|
694
|
+
"Use GetStaticMethodInvoker for static methods",
|
|
695
|
+
nameof(method)
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
#if !EMIT_DYNAMIC_IL
|
|
700
|
+
return CreateCompiledMethodInvoker(method);
|
|
701
|
+
#else
|
|
702
|
+
DynamicMethod dynamicMethod = new(
|
|
703
|
+
$"Invoke{method.DeclaringType.Name}_{method.Name}",
|
|
704
|
+
typeof(object),
|
|
705
|
+
new[] { typeof(object), typeof(object[]) },
|
|
706
|
+
method.DeclaringType,
|
|
707
|
+
true
|
|
708
|
+
);
|
|
709
|
+
|
|
710
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
711
|
+
ParameterInfo[] parameters = method.GetParameters();
|
|
712
|
+
|
|
713
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
714
|
+
il.Emit(
|
|
715
|
+
method.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
|
|
716
|
+
method.DeclaringType
|
|
717
|
+
);
|
|
718
|
+
|
|
719
|
+
for (int i = 0; i < parameters.Length; i++)
|
|
720
|
+
{
|
|
721
|
+
il.Emit(OpCodes.Ldarg_1);
|
|
722
|
+
il.Emit(OpCodes.Ldc_I4, i);
|
|
723
|
+
il.Emit(OpCodes.Ldelem_Ref);
|
|
724
|
+
|
|
725
|
+
Type paramType = parameters[i].ParameterType;
|
|
726
|
+
if (paramType.IsValueType)
|
|
727
|
+
{
|
|
728
|
+
il.Emit(OpCodes.Unbox_Any, paramType);
|
|
729
|
+
}
|
|
730
|
+
else
|
|
731
|
+
{
|
|
732
|
+
il.Emit(OpCodes.Castclass, paramType);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
il.Emit(method.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt, method);
|
|
737
|
+
|
|
738
|
+
if (method.ReturnType == typeof(void))
|
|
739
|
+
{
|
|
740
|
+
il.Emit(OpCodes.Ldnull);
|
|
741
|
+
}
|
|
742
|
+
else if (method.ReturnType.IsValueType)
|
|
743
|
+
{
|
|
744
|
+
il.Emit(OpCodes.Box, method.ReturnType);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
il.Emit(OpCodes.Ret);
|
|
748
|
+
|
|
749
|
+
return (Func<object, object[], object>)
|
|
750
|
+
dynamicMethod.CreateDelegate(typeof(Func<object, object[], object>));
|
|
751
|
+
#endif
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
public static Func<object[], object> GetStaticMethodInvoker(MethodInfo method)
|
|
755
|
+
{
|
|
756
|
+
if (!method.IsStatic)
|
|
757
|
+
{
|
|
758
|
+
throw new ArgumentException("Method must be static", nameof(method));
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
#if !EMIT_DYNAMIC_IL
|
|
762
|
+
return CreateCompiledStaticMethodInvoker(method);
|
|
763
|
+
#else
|
|
764
|
+
DynamicMethod dynamicMethod = new(
|
|
765
|
+
$"InvokeStatic{method.DeclaringType.Name}_{method.Name}",
|
|
766
|
+
typeof(object),
|
|
767
|
+
new[] { typeof(object[]) },
|
|
768
|
+
method.DeclaringType,
|
|
769
|
+
true
|
|
770
|
+
);
|
|
771
|
+
|
|
772
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
773
|
+
ParameterInfo[] parameters = method.GetParameters();
|
|
774
|
+
|
|
775
|
+
for (int i = 0; i < parameters.Length; i++)
|
|
776
|
+
{
|
|
777
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
778
|
+
il.Emit(OpCodes.Ldc_I4, i);
|
|
779
|
+
il.Emit(OpCodes.Ldelem_Ref);
|
|
780
|
+
|
|
781
|
+
Type paramType = parameters[i].ParameterType;
|
|
782
|
+
if (paramType.IsValueType)
|
|
783
|
+
{
|
|
784
|
+
il.Emit(OpCodes.Unbox_Any, paramType);
|
|
785
|
+
}
|
|
786
|
+
else
|
|
787
|
+
{
|
|
788
|
+
il.Emit(OpCodes.Castclass, paramType);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
il.Emit(OpCodes.Call, method);
|
|
793
|
+
|
|
794
|
+
if (method.ReturnType == typeof(void))
|
|
795
|
+
{
|
|
796
|
+
il.Emit(OpCodes.Ldnull);
|
|
797
|
+
}
|
|
798
|
+
else if (method.ReturnType.IsValueType)
|
|
799
|
+
{
|
|
800
|
+
il.Emit(OpCodes.Box, method.ReturnType);
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
il.Emit(OpCodes.Ret);
|
|
804
|
+
|
|
805
|
+
return (Func<object[], object>)
|
|
806
|
+
dynamicMethod.CreateDelegate(typeof(Func<object[], object>));
|
|
807
|
+
#endif
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
public static Func<object[], object> GetConstructor(ConstructorInfo constructor)
|
|
811
|
+
{
|
|
812
|
+
#if !EMIT_DYNAMIC_IL
|
|
813
|
+
return CreateCompiledConstructor(constructor);
|
|
814
|
+
#else
|
|
815
|
+
DynamicMethod dynamicMethod = new(
|
|
816
|
+
$"Create{constructor.DeclaringType.Name}",
|
|
817
|
+
typeof(object),
|
|
818
|
+
new[] { typeof(object[]) },
|
|
819
|
+
constructor.DeclaringType,
|
|
820
|
+
true
|
|
821
|
+
);
|
|
822
|
+
|
|
823
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
824
|
+
ParameterInfo[] parameters = constructor.GetParameters();
|
|
825
|
+
|
|
826
|
+
for (int i = 0; i < parameters.Length; i++)
|
|
827
|
+
{
|
|
828
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
829
|
+
il.Emit(OpCodes.Ldc_I4, i);
|
|
830
|
+
il.Emit(OpCodes.Ldelem_Ref);
|
|
831
|
+
|
|
832
|
+
Type paramType = parameters[i].ParameterType;
|
|
833
|
+
if (paramType.IsValueType)
|
|
834
|
+
{
|
|
835
|
+
il.Emit(OpCodes.Unbox_Any, paramType);
|
|
836
|
+
}
|
|
837
|
+
else
|
|
838
|
+
{
|
|
839
|
+
il.Emit(OpCodes.Castclass, paramType);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
il.Emit(OpCodes.Newobj, constructor);
|
|
844
|
+
|
|
845
|
+
if (constructor.DeclaringType.IsValueType)
|
|
846
|
+
{
|
|
847
|
+
il.Emit(OpCodes.Box, constructor.DeclaringType);
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
il.Emit(OpCodes.Ret);
|
|
851
|
+
|
|
852
|
+
return (Func<object[], object>)
|
|
853
|
+
dynamicMethod.CreateDelegate(typeof(Func<object[], object>));
|
|
854
|
+
#endif
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
public static Func<T> GetParameterlessConstructor<T>()
|
|
858
|
+
{
|
|
859
|
+
Type type = typeof(T);
|
|
860
|
+
ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes);
|
|
861
|
+
if (constructor == null)
|
|
862
|
+
{
|
|
863
|
+
throw new ArgumentException(
|
|
864
|
+
$"Type {type.Name} does not have a parameterless constructor"
|
|
865
|
+
);
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
#if !EMIT_DYNAMIC_IL
|
|
869
|
+
return CreateCompiledParameterlessConstructor<T>(constructor);
|
|
870
|
+
#else
|
|
871
|
+
DynamicMethod dynamicMethod = new(
|
|
872
|
+
$"CreateParameterless{type.Name}",
|
|
873
|
+
typeof(T),
|
|
874
|
+
Type.EmptyTypes,
|
|
875
|
+
type,
|
|
876
|
+
true
|
|
877
|
+
);
|
|
878
|
+
|
|
879
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
880
|
+
il.Emit(OpCodes.Newobj, constructor);
|
|
881
|
+
il.Emit(OpCodes.Ret);
|
|
882
|
+
|
|
883
|
+
return (Func<T>)dynamicMethod.CreateDelegate(typeof(Func<T>));
|
|
884
|
+
#endif
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
public static Func<T> GetGenericParameterlessConstructor<T>(
|
|
888
|
+
Type genericTypeDefinition,
|
|
889
|
+
params Type[] genericArguments
|
|
890
|
+
)
|
|
891
|
+
{
|
|
892
|
+
Type constructedType = genericTypeDefinition.MakeGenericType(genericArguments);
|
|
893
|
+
ConstructorInfo constructor = constructedType.GetConstructor(Type.EmptyTypes);
|
|
894
|
+
if (constructor == null)
|
|
895
|
+
{
|
|
896
|
+
throw new ArgumentException(
|
|
897
|
+
$"Type {constructedType.Name} does not have a parameterless constructor"
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
#if !EMIT_DYNAMIC_IL
|
|
902
|
+
return CreateCompiledGenericParameterlessConstructor<T>(constructedType, constructor);
|
|
903
|
+
#else
|
|
904
|
+
DynamicMethod dynamicMethod = new(
|
|
905
|
+
$"CreateGenericParameterless{constructedType.Name}",
|
|
906
|
+
typeof(T),
|
|
907
|
+
Type.EmptyTypes,
|
|
908
|
+
constructedType,
|
|
909
|
+
true
|
|
910
|
+
);
|
|
911
|
+
|
|
912
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
913
|
+
il.Emit(OpCodes.Newobj, constructor);
|
|
914
|
+
if (constructedType.IsValueType && typeof(T) == typeof(object))
|
|
915
|
+
{
|
|
916
|
+
il.Emit(OpCodes.Box, constructedType);
|
|
917
|
+
}
|
|
918
|
+
il.Emit(OpCodes.Ret);
|
|
919
|
+
|
|
920
|
+
return (Func<T>)dynamicMethod.CreateDelegate(typeof(Func<T>));
|
|
921
|
+
#endif
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
public static IEnumerable<Type> GetAllLoadedTypes()
|
|
925
|
+
{
|
|
926
|
+
return GetAllLoadedAssemblies()
|
|
927
|
+
.SelectMany(assembly => GetTypesFromAssembly(assembly))
|
|
928
|
+
.Where(type => type != null);
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
public static IEnumerable<Assembly> GetAllLoadedAssemblies()
|
|
932
|
+
{
|
|
933
|
+
try
|
|
934
|
+
{
|
|
935
|
+
return AppDomain
|
|
936
|
+
.CurrentDomain.GetAssemblies()
|
|
937
|
+
.Where(assembly => assembly != null && !assembly.IsDynamic);
|
|
938
|
+
}
|
|
939
|
+
catch
|
|
940
|
+
{
|
|
941
|
+
return Enumerable.Empty<Assembly>();
|
|
942
|
+
}
|
|
943
|
+
}
|
|
944
|
+
|
|
945
|
+
public static Type[] GetTypesFromAssembly(Assembly assembly)
|
|
946
|
+
{
|
|
947
|
+
if (assembly == null)
|
|
948
|
+
{
|
|
949
|
+
return Type.EmptyTypes;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
try
|
|
953
|
+
{
|
|
954
|
+
return assembly.GetTypes();
|
|
955
|
+
}
|
|
956
|
+
catch (ReflectionTypeLoadException ex)
|
|
957
|
+
{
|
|
958
|
+
return ex.Types.Where(t => t != null).ToArray();
|
|
959
|
+
}
|
|
960
|
+
catch
|
|
961
|
+
{
|
|
962
|
+
return Type.EmptyTypes;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
public static Type[] GetTypesFromAssemblyName(string assemblyName)
|
|
967
|
+
{
|
|
968
|
+
try
|
|
969
|
+
{
|
|
970
|
+
Assembly assembly = Assembly.Load(assemblyName);
|
|
971
|
+
return GetTypesFromAssembly(assembly);
|
|
972
|
+
}
|
|
973
|
+
catch
|
|
974
|
+
{
|
|
975
|
+
return Type.EmptyTypes;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
public static IEnumerable<Type> GetTypesWithAttribute<TAttribute>()
|
|
980
|
+
where TAttribute : Attribute
|
|
981
|
+
{
|
|
982
|
+
return GetAllLoadedTypes().Where(type => HasAttributeSafe<TAttribute>(type));
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
public static IEnumerable<Type> GetTypesWithAttribute(Type attributeType)
|
|
986
|
+
{
|
|
987
|
+
if (attributeType == null || !typeof(Attribute).IsAssignableFrom(attributeType))
|
|
988
|
+
{
|
|
989
|
+
return Enumerable.Empty<Type>();
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
return GetAllLoadedTypes().Where(type => HasAttributeSafe(type, attributeType));
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
public static bool HasAttributeSafe<TAttribute>(
|
|
996
|
+
ICustomAttributeProvider provider,
|
|
997
|
+
bool inherit = true
|
|
998
|
+
)
|
|
999
|
+
where TAttribute : Attribute
|
|
1000
|
+
{
|
|
1001
|
+
if (provider == null)
|
|
1002
|
+
{
|
|
1003
|
+
return false;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
try
|
|
1007
|
+
{
|
|
1008
|
+
return provider.IsDefined(typeof(TAttribute), inherit);
|
|
1009
|
+
}
|
|
1010
|
+
catch
|
|
1011
|
+
{
|
|
1012
|
+
return false;
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
public static bool HasAttributeSafe(
|
|
1017
|
+
ICustomAttributeProvider provider,
|
|
1018
|
+
Type attributeType,
|
|
1019
|
+
bool inherit = true
|
|
1020
|
+
)
|
|
1021
|
+
{
|
|
1022
|
+
if (provider == null || attributeType == null)
|
|
1023
|
+
{
|
|
1024
|
+
return false;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
try
|
|
1028
|
+
{
|
|
1029
|
+
return provider.IsDefined(attributeType, inherit);
|
|
1030
|
+
}
|
|
1031
|
+
catch
|
|
1032
|
+
{
|
|
1033
|
+
return false;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
public static TAttribute GetAttributeSafe<TAttribute>(
|
|
1038
|
+
ICustomAttributeProvider provider,
|
|
1039
|
+
bool inherit = true
|
|
1040
|
+
)
|
|
1041
|
+
where TAttribute : Attribute
|
|
1042
|
+
{
|
|
1043
|
+
if (provider == null)
|
|
1044
|
+
{
|
|
1045
|
+
return default;
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
try
|
|
1049
|
+
{
|
|
1050
|
+
if (provider.IsDefined(typeof(TAttribute), inherit))
|
|
1051
|
+
{
|
|
1052
|
+
object[] attributes = provider.GetCustomAttributes(typeof(TAttribute), inherit);
|
|
1053
|
+
return attributes.Length > 0 ? attributes[0] as TAttribute : default;
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
catch
|
|
1057
|
+
{
|
|
1058
|
+
// Swallow
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
return default;
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
public static Attribute GetAttributeSafe(
|
|
1065
|
+
ICustomAttributeProvider provider,
|
|
1066
|
+
Type attributeType,
|
|
1067
|
+
bool inherit = true
|
|
1068
|
+
)
|
|
1069
|
+
{
|
|
1070
|
+
if (provider == null || attributeType == null)
|
|
1071
|
+
{
|
|
1072
|
+
return null;
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
try
|
|
1076
|
+
{
|
|
1077
|
+
if (provider.IsDefined(attributeType, inherit))
|
|
1078
|
+
{
|
|
1079
|
+
object[] attributes = provider.GetCustomAttributes(attributeType, inherit);
|
|
1080
|
+
return attributes.Length > 0 ? attributes[0] as Attribute : null;
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
catch
|
|
1084
|
+
{
|
|
1085
|
+
// Swallow
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
return null;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
public static TAttribute[] GetAllAttributesSafe<TAttribute>(
|
|
1092
|
+
ICustomAttributeProvider provider,
|
|
1093
|
+
bool inherit = true
|
|
1094
|
+
)
|
|
1095
|
+
where TAttribute : Attribute
|
|
1096
|
+
{
|
|
1097
|
+
if (provider == null)
|
|
1098
|
+
{
|
|
1099
|
+
return Array.Empty<TAttribute>();
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
try
|
|
1103
|
+
{
|
|
1104
|
+
if (provider.IsDefined(typeof(TAttribute), inherit))
|
|
1105
|
+
{
|
|
1106
|
+
return provider
|
|
1107
|
+
.GetCustomAttributes(typeof(TAttribute), inherit)
|
|
1108
|
+
.OfType<TAttribute>()
|
|
1109
|
+
.ToArray();
|
|
1110
|
+
}
|
|
1111
|
+
return Array.Empty<TAttribute>();
|
|
1112
|
+
}
|
|
1113
|
+
catch
|
|
1114
|
+
{
|
|
1115
|
+
return Array.Empty<TAttribute>();
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
public static Attribute[] GetAllAttributesSafe(
|
|
1120
|
+
ICustomAttributeProvider provider,
|
|
1121
|
+
bool inherit = true
|
|
1122
|
+
)
|
|
1123
|
+
{
|
|
1124
|
+
if (provider == null)
|
|
1125
|
+
{
|
|
1126
|
+
return Array.Empty<Attribute>();
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
try
|
|
1130
|
+
{
|
|
1131
|
+
return provider.GetCustomAttributes(inherit).OfType<Attribute>().ToArray();
|
|
1132
|
+
}
|
|
1133
|
+
catch
|
|
1134
|
+
{
|
|
1135
|
+
return Array.Empty<Attribute>();
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
public static Attribute[] GetAllAttributesSafe(
|
|
1140
|
+
ICustomAttributeProvider provider,
|
|
1141
|
+
Type attributeType,
|
|
1142
|
+
bool inherit = true
|
|
1143
|
+
)
|
|
1144
|
+
{
|
|
1145
|
+
if (provider == null || attributeType == null)
|
|
1146
|
+
{
|
|
1147
|
+
return Array.Empty<Attribute>();
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
try
|
|
1151
|
+
{
|
|
1152
|
+
if (provider.IsDefined(attributeType, inherit))
|
|
1153
|
+
{
|
|
1154
|
+
return provider
|
|
1155
|
+
.GetCustomAttributes(attributeType, inherit)
|
|
1156
|
+
.OfType<Attribute>()
|
|
1157
|
+
.ToArray();
|
|
1158
|
+
}
|
|
1159
|
+
return Array.Empty<Attribute>();
|
|
1160
|
+
}
|
|
1161
|
+
catch
|
|
1162
|
+
{
|
|
1163
|
+
return Array.Empty<Attribute>();
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
public static Dictionary<string, object> GetAllAttributeValuesSafe(
|
|
1168
|
+
ICustomAttributeProvider provider,
|
|
1169
|
+
bool inherit = true
|
|
1170
|
+
)
|
|
1171
|
+
{
|
|
1172
|
+
Dictionary<string, object> result = new();
|
|
1173
|
+
|
|
1174
|
+
foreach (Attribute attr in GetAllAttributesSafe(provider, inherit))
|
|
1175
|
+
{
|
|
1176
|
+
try
|
|
1177
|
+
{
|
|
1178
|
+
Type attrType = attr.GetType();
|
|
1179
|
+
string key = attrType.Name;
|
|
1180
|
+
|
|
1181
|
+
if (key.EndsWith("Attribute"))
|
|
1182
|
+
{
|
|
1183
|
+
key = key.Substring(0, key.Length - 9);
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
result.TryAdd(key, attr);
|
|
1187
|
+
}
|
|
1188
|
+
catch
|
|
1189
|
+
{
|
|
1190
|
+
// Skip this attribute if we can't process it
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
return result;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
public static MethodInfo[] GetMethodsWithAttributeSafe<TAttribute>(
|
|
1198
|
+
Type type,
|
|
1199
|
+
bool inherit = true
|
|
1200
|
+
)
|
|
1201
|
+
where TAttribute : Attribute
|
|
1202
|
+
{
|
|
1203
|
+
if (type == null)
|
|
1204
|
+
{
|
|
1205
|
+
return Array.Empty<MethodInfo>();
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
try
|
|
1209
|
+
{
|
|
1210
|
+
bool localInherit = inherit;
|
|
1211
|
+
return type.GetMethods(
|
|
1212
|
+
BindingFlags.Public
|
|
1213
|
+
| BindingFlags.NonPublic
|
|
1214
|
+
| BindingFlags.Instance
|
|
1215
|
+
| BindingFlags.Static
|
|
1216
|
+
)
|
|
1217
|
+
.Where(method => HasAttributeSafe<TAttribute>(method, localInherit))
|
|
1218
|
+
.ToArray();
|
|
1219
|
+
}
|
|
1220
|
+
catch
|
|
1221
|
+
{
|
|
1222
|
+
return Array.Empty<MethodInfo>();
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
public static PropertyInfo[] GetPropertiesWithAttributeSafe<TAttribute>(
|
|
1227
|
+
Type type,
|
|
1228
|
+
bool inherit = true
|
|
1229
|
+
)
|
|
1230
|
+
where TAttribute : Attribute
|
|
1231
|
+
{
|
|
1232
|
+
if (type == null)
|
|
1233
|
+
{
|
|
1234
|
+
return Array.Empty<PropertyInfo>();
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
try
|
|
1238
|
+
{
|
|
1239
|
+
bool localInherit = inherit;
|
|
1240
|
+
return type.GetProperties(
|
|
1241
|
+
BindingFlags.Public
|
|
1242
|
+
| BindingFlags.NonPublic
|
|
1243
|
+
| BindingFlags.Instance
|
|
1244
|
+
| BindingFlags.Static
|
|
1245
|
+
)
|
|
1246
|
+
.Where(property => HasAttributeSafe<TAttribute>(property, localInherit))
|
|
1247
|
+
.ToArray();
|
|
1248
|
+
}
|
|
1249
|
+
catch
|
|
1250
|
+
{
|
|
1251
|
+
return Array.Empty<PropertyInfo>();
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
public static FieldInfo[] GetFieldsWithAttributeSafe<TAttribute>(
|
|
1256
|
+
Type type,
|
|
1257
|
+
bool inherit = true
|
|
1258
|
+
)
|
|
1259
|
+
where TAttribute : Attribute
|
|
1260
|
+
{
|
|
1261
|
+
if (type == null)
|
|
1262
|
+
{
|
|
1263
|
+
return Array.Empty<FieldInfo>();
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
try
|
|
1267
|
+
{
|
|
1268
|
+
bool localInherit = inherit;
|
|
1269
|
+
return type.GetFields(
|
|
1270
|
+
BindingFlags.Public
|
|
1271
|
+
| BindingFlags.NonPublic
|
|
1272
|
+
| BindingFlags.Instance
|
|
1273
|
+
| BindingFlags.Static
|
|
1274
|
+
)
|
|
1275
|
+
.Where(field => HasAttributeSafe<TAttribute>(field, localInherit))
|
|
1276
|
+
.ToArray();
|
|
1277
|
+
}
|
|
1278
|
+
catch
|
|
1279
|
+
{
|
|
1280
|
+
return Array.Empty<FieldInfo>();
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
private static bool CheckExpressionCompilationSupport()
|
|
1285
|
+
{
|
|
1286
|
+
#if !SUPPORT_EXPRESSION_COMPILE
|
|
1287
|
+
return false;
|
|
1288
|
+
#else
|
|
1289
|
+
try
|
|
1290
|
+
{
|
|
1291
|
+
// Test if expression compilation works by trying a simple lambda
|
|
1292
|
+
Expression<Func<int>> testExpr = () => 42;
|
|
1293
|
+
Func<int> compiled = testExpr.Compile();
|
|
1294
|
+
return compiled() == 42;
|
|
1295
|
+
}
|
|
1296
|
+
catch
|
|
1297
|
+
{
|
|
1298
|
+
return false;
|
|
1299
|
+
}
|
|
1300
|
+
#endif
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
private static Func<object, object[], object> CreateCompiledMethodInvoker(MethodInfo method)
|
|
1304
|
+
{
|
|
1305
|
+
if (!CanCompileExpressions)
|
|
1306
|
+
{
|
|
1307
|
+
return CreateDelegateMethodInvoker(method)
|
|
1308
|
+
?? ((instance, args) => method.Invoke(instance, args));
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
try
|
|
1312
|
+
{
|
|
1313
|
+
ParameterExpression instanceParam = Expression.Parameter(
|
|
1314
|
+
typeof(object),
|
|
1315
|
+
"instance"
|
|
1316
|
+
);
|
|
1317
|
+
ParameterExpression argsParam = Expression.Parameter(typeof(object[]), "args");
|
|
1318
|
+
|
|
1319
|
+
Expression instanceExpression = method.DeclaringType.IsValueType
|
|
1320
|
+
? Expression.Unbox(instanceParam, method.DeclaringType)
|
|
1321
|
+
: Expression.Convert(instanceParam, method.DeclaringType);
|
|
1322
|
+
|
|
1323
|
+
ParameterInfo[] parameters = method.GetParameters();
|
|
1324
|
+
Expression[] paramExpressions = new Expression[parameters.Length];
|
|
1325
|
+
|
|
1326
|
+
for (int i = 0; i < parameters.Length; i++)
|
|
1327
|
+
{
|
|
1328
|
+
Expression argExpression = Expression.ArrayIndex(
|
|
1329
|
+
argsParam,
|
|
1330
|
+
Expression.Constant(i)
|
|
1331
|
+
);
|
|
1332
|
+
Type paramType = parameters[i].ParameterType;
|
|
1333
|
+
paramExpressions[i] = paramType.IsValueType
|
|
1334
|
+
? Expression.Unbox(argExpression, paramType)
|
|
1335
|
+
: Expression.Convert(argExpression, paramType);
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
Expression callExpression = Expression.Call(
|
|
1339
|
+
instanceExpression,
|
|
1340
|
+
method,
|
|
1341
|
+
paramExpressions
|
|
1342
|
+
);
|
|
1343
|
+
|
|
1344
|
+
Expression returnExpression =
|
|
1345
|
+
method.ReturnType == typeof(void)
|
|
1346
|
+
? Expression.Block(callExpression, Expression.Constant(null))
|
|
1347
|
+
: method.ReturnType.IsValueType
|
|
1348
|
+
? Expression.Convert(callExpression, typeof(object))
|
|
1349
|
+
: callExpression;
|
|
1350
|
+
|
|
1351
|
+
return Expression
|
|
1352
|
+
.Lambda<Func<object, object[], object>>(
|
|
1353
|
+
returnExpression,
|
|
1354
|
+
instanceParam,
|
|
1355
|
+
argsParam
|
|
1356
|
+
)
|
|
1357
|
+
.Compile();
|
|
1358
|
+
}
|
|
1359
|
+
catch
|
|
1360
|
+
{
|
|
1361
|
+
return (instance, args) => method.Invoke(instance, args);
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
private static Func<object[], object> CreateCompiledStaticMethodInvoker(MethodInfo method)
|
|
1366
|
+
{
|
|
1367
|
+
if (!CanCompileExpressions)
|
|
1368
|
+
{
|
|
1369
|
+
return CreateDelegateStaticMethodInvoker(method)
|
|
1370
|
+
?? (args => method.Invoke(null, args));
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
try
|
|
1374
|
+
{
|
|
1375
|
+
ParameterExpression argsParam = Expression.Parameter(typeof(object[]), "args");
|
|
1376
|
+
|
|
1377
|
+
ParameterInfo[] parameters = method.GetParameters();
|
|
1378
|
+
Expression[] paramExpressions = new Expression[parameters.Length];
|
|
1379
|
+
|
|
1380
|
+
for (int i = 0; i < parameters.Length; i++)
|
|
1381
|
+
{
|
|
1382
|
+
Expression argExpression = Expression.ArrayIndex(
|
|
1383
|
+
argsParam,
|
|
1384
|
+
Expression.Constant(i)
|
|
1385
|
+
);
|
|
1386
|
+
Type paramType = parameters[i].ParameterType;
|
|
1387
|
+
paramExpressions[i] = paramType.IsValueType
|
|
1388
|
+
? Expression.Unbox(argExpression, paramType)
|
|
1389
|
+
: Expression.Convert(argExpression, paramType);
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
Expression callExpression = Expression.Call(method, paramExpressions);
|
|
1393
|
+
|
|
1394
|
+
Expression returnExpression =
|
|
1395
|
+
method.ReturnType == typeof(void)
|
|
1396
|
+
? Expression.Block(callExpression, Expression.Constant(null))
|
|
1397
|
+
: method.ReturnType.IsValueType
|
|
1398
|
+
? Expression.Convert(callExpression, typeof(object))
|
|
1399
|
+
: callExpression;
|
|
1400
|
+
|
|
1401
|
+
return Expression
|
|
1402
|
+
.Lambda<Func<object[], object>>(returnExpression, argsParam)
|
|
1403
|
+
.Compile();
|
|
1404
|
+
}
|
|
1405
|
+
catch
|
|
1406
|
+
{
|
|
1407
|
+
return args => method.Invoke(null, args);
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
private static Func<object[], object> CreateCompiledConstructor(ConstructorInfo constructor)
|
|
1412
|
+
{
|
|
1413
|
+
if (!CanCompileExpressions)
|
|
1414
|
+
{
|
|
1415
|
+
return CreateDelegateConstructor(constructor) ?? (args => constructor.Invoke(args));
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
try
|
|
1419
|
+
{
|
|
1420
|
+
ParameterExpression argsParam = Expression.Parameter(typeof(object[]), "args");
|
|
1421
|
+
|
|
1422
|
+
ParameterInfo[] parameters = constructor.GetParameters();
|
|
1423
|
+
Expression[] paramExpressions = new Expression[parameters.Length];
|
|
1424
|
+
|
|
1425
|
+
for (int i = 0; i < parameters.Length; i++)
|
|
1426
|
+
{
|
|
1427
|
+
Expression argExpression = Expression.ArrayIndex(
|
|
1428
|
+
argsParam,
|
|
1429
|
+
Expression.Constant(i)
|
|
1430
|
+
);
|
|
1431
|
+
Type paramType = parameters[i].ParameterType;
|
|
1432
|
+
paramExpressions[i] = paramType.IsValueType
|
|
1433
|
+
? Expression.Unbox(argExpression, paramType)
|
|
1434
|
+
: Expression.Convert(argExpression, paramType);
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
Expression newExpression = Expression.New(constructor, paramExpressions);
|
|
1438
|
+
|
|
1439
|
+
Expression returnExpression = constructor.DeclaringType.IsValueType
|
|
1440
|
+
? Expression.Convert(newExpression, typeof(object))
|
|
1441
|
+
: newExpression;
|
|
1442
|
+
|
|
1443
|
+
return Expression
|
|
1444
|
+
.Lambda<Func<object[], object>>(returnExpression, argsParam)
|
|
1445
|
+
.Compile();
|
|
1446
|
+
}
|
|
1447
|
+
catch
|
|
1448
|
+
{
|
|
1449
|
+
return args => constructor.Invoke(args);
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
private static Func<T> CreateCompiledParameterlessConstructor<T>(
|
|
1454
|
+
ConstructorInfo constructor
|
|
1455
|
+
)
|
|
1456
|
+
{
|
|
1457
|
+
if (!CanCompileExpressions)
|
|
1458
|
+
{
|
|
1459
|
+
return CreateDelegateParameterlessConstructor<T>(constructor)
|
|
1460
|
+
?? (() => (T)Activator.CreateInstance(typeof(T)));
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
try
|
|
1464
|
+
{
|
|
1465
|
+
Expression newExpression = Expression.New(constructor);
|
|
1466
|
+
return Expression.Lambda<Func<T>>(newExpression).Compile();
|
|
1467
|
+
}
|
|
1468
|
+
catch
|
|
1469
|
+
{
|
|
1470
|
+
return () => (T)Activator.CreateInstance(typeof(T));
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
private static Func<T> CreateCompiledGenericParameterlessConstructor<T>(
|
|
1475
|
+
Type constructedType,
|
|
1476
|
+
ConstructorInfo constructor
|
|
1477
|
+
)
|
|
1478
|
+
{
|
|
1479
|
+
if (!CanCompileExpressions)
|
|
1480
|
+
{
|
|
1481
|
+
return () => (T)Activator.CreateInstance(constructedType);
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
try
|
|
1485
|
+
{
|
|
1486
|
+
Expression newExpression = Expression.New(constructor);
|
|
1487
|
+
Expression convertExpression =
|
|
1488
|
+
constructedType.IsValueType && typeof(T) == typeof(object)
|
|
1489
|
+
? Expression.Convert(newExpression, typeof(object))
|
|
1490
|
+
: newExpression;
|
|
1491
|
+
|
|
1492
|
+
return Expression.Lambda<Func<T>>(convertExpression).Compile();
|
|
1493
|
+
}
|
|
1494
|
+
catch
|
|
1495
|
+
{
|
|
1496
|
+
return () => (T)Activator.CreateInstance(constructedType);
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
private static Func<object, object> CreateCompiledFieldGetter(FieldInfo field)
|
|
1501
|
+
{
|
|
1502
|
+
if (!CanCompileExpressions)
|
|
1503
|
+
{
|
|
1504
|
+
return CreateDelegateFieldGetter(field) ?? field.GetValue;
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
try
|
|
1508
|
+
{
|
|
1509
|
+
ParameterExpression instanceParam = Expression.Parameter(
|
|
1510
|
+
typeof(object),
|
|
1511
|
+
"instance"
|
|
1512
|
+
);
|
|
1513
|
+
|
|
1514
|
+
Expression instanceExpression = field.DeclaringType.IsValueType
|
|
1515
|
+
? Expression.Unbox(instanceParam, field.DeclaringType)
|
|
1516
|
+
: Expression.Convert(instanceParam, field.DeclaringType);
|
|
1517
|
+
|
|
1518
|
+
Expression fieldExpression = Expression.Field(instanceExpression, field);
|
|
1519
|
+
|
|
1520
|
+
Expression returnExpression = field.FieldType.IsValueType
|
|
1521
|
+
? Expression.Convert(fieldExpression, typeof(object))
|
|
1522
|
+
: fieldExpression;
|
|
1523
|
+
|
|
1524
|
+
return Expression
|
|
1525
|
+
.Lambda<Func<object, object>>(returnExpression, instanceParam)
|
|
1526
|
+
.Compile();
|
|
1527
|
+
}
|
|
1528
|
+
catch
|
|
1529
|
+
{
|
|
1530
|
+
return field.GetValue;
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
private static Func<object, object> CreateCompiledPropertyGetter(PropertyInfo property)
|
|
1535
|
+
{
|
|
1536
|
+
if (!CanCompileExpressions)
|
|
1537
|
+
{
|
|
1538
|
+
return CreateDelegatePropertyGetter(property) ?? property.GetValue;
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
try
|
|
1542
|
+
{
|
|
1543
|
+
MethodInfo getMethod = property.GetGetMethod(true);
|
|
1544
|
+
if (getMethod == null)
|
|
1545
|
+
{
|
|
1546
|
+
return property.GetValue;
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
ParameterExpression instanceParam = Expression.Parameter(
|
|
1550
|
+
typeof(object),
|
|
1551
|
+
"instance"
|
|
1552
|
+
);
|
|
1553
|
+
|
|
1554
|
+
Expression instanceExpression = property.DeclaringType.IsValueType
|
|
1555
|
+
? Expression.Unbox(instanceParam, property.DeclaringType)
|
|
1556
|
+
: Expression.Convert(instanceParam, property.DeclaringType);
|
|
1557
|
+
|
|
1558
|
+
Expression propertyExpression = Expression.Property(instanceExpression, property);
|
|
1559
|
+
|
|
1560
|
+
Expression returnExpression = property.PropertyType.IsValueType
|
|
1561
|
+
? Expression.Convert(propertyExpression, typeof(object))
|
|
1562
|
+
: propertyExpression;
|
|
1563
|
+
|
|
1564
|
+
return Expression
|
|
1565
|
+
.Lambda<Func<object, object>>(returnExpression, instanceParam)
|
|
1566
|
+
.Compile();
|
|
1567
|
+
}
|
|
1568
|
+
catch
|
|
1569
|
+
{
|
|
1570
|
+
return property.GetValue;
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
private static Func<object> CreateCompiledStaticFieldGetter(FieldInfo field)
|
|
1575
|
+
{
|
|
1576
|
+
if (!CanCompileExpressions)
|
|
1577
|
+
{
|
|
1578
|
+
return () => field.GetValue(null);
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
try
|
|
1582
|
+
{
|
|
1583
|
+
Expression fieldExpression = Expression.Field(null, field);
|
|
1584
|
+
|
|
1585
|
+
Expression returnExpression = field.FieldType.IsValueType
|
|
1586
|
+
? Expression.Convert(fieldExpression, typeof(object))
|
|
1587
|
+
: fieldExpression;
|
|
1588
|
+
|
|
1589
|
+
return Expression.Lambda<Func<object>>(returnExpression).Compile();
|
|
1590
|
+
}
|
|
1591
|
+
catch
|
|
1592
|
+
{
|
|
1593
|
+
return () => field.GetValue(null);
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
private static Action<object, object> CreateCompiledFieldSetter(FieldInfo field)
|
|
1598
|
+
{
|
|
1599
|
+
if (!CanCompileExpressions)
|
|
1600
|
+
{
|
|
1601
|
+
return field.SetValue;
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
try
|
|
1605
|
+
{
|
|
1606
|
+
ParameterExpression instanceParam = Expression.Parameter(
|
|
1607
|
+
typeof(object),
|
|
1608
|
+
"instance"
|
|
1609
|
+
);
|
|
1610
|
+
ParameterExpression valueParam = Expression.Parameter(typeof(object), "value");
|
|
1611
|
+
|
|
1612
|
+
Expression instanceExpression = field.DeclaringType.IsValueType
|
|
1613
|
+
? Expression.Unbox(instanceParam, field.DeclaringType)
|
|
1614
|
+
: Expression.Convert(instanceParam, field.DeclaringType);
|
|
1615
|
+
|
|
1616
|
+
Expression valueExpression = field.FieldType.IsValueType
|
|
1617
|
+
? Expression.Unbox(valueParam, field.FieldType)
|
|
1618
|
+
: Expression.Convert(valueParam, field.FieldType);
|
|
1619
|
+
|
|
1620
|
+
Expression assignExpression = Expression.Assign(
|
|
1621
|
+
Expression.Field(instanceExpression, field),
|
|
1622
|
+
valueExpression
|
|
1623
|
+
);
|
|
1624
|
+
|
|
1625
|
+
return Expression
|
|
1626
|
+
.Lambda<Action<object, object>>(assignExpression, instanceParam, valueParam)
|
|
1627
|
+
.Compile();
|
|
1628
|
+
}
|
|
1629
|
+
catch
|
|
1630
|
+
{
|
|
1631
|
+
return field.SetValue;
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
|
|
1635
|
+
private static Action<object> CreateCompiledStaticFieldSetter(FieldInfo field)
|
|
1636
|
+
{
|
|
1637
|
+
if (!CanCompileExpressions)
|
|
1638
|
+
{
|
|
1639
|
+
return value => field.SetValue(null, value);
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
try
|
|
1643
|
+
{
|
|
1644
|
+
ParameterExpression valueParam = Expression.Parameter(typeof(object), "value");
|
|
1645
|
+
|
|
1646
|
+
Expression valueExpression = field.FieldType.IsValueType
|
|
1647
|
+
? Expression.Unbox(valueParam, field.FieldType)
|
|
1648
|
+
: Expression.Convert(valueParam, field.FieldType);
|
|
1649
|
+
|
|
1650
|
+
Expression assignExpression = Expression.Assign(
|
|
1651
|
+
Expression.Field(null, field),
|
|
1652
|
+
valueExpression
|
|
1653
|
+
);
|
|
1654
|
+
|
|
1655
|
+
return Expression.Lambda<Action<object>>(assignExpression, valueParam).Compile();
|
|
1656
|
+
}
|
|
1657
|
+
catch
|
|
1658
|
+
{
|
|
1659
|
+
return value => field.SetValue(null, value);
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
private static Func<object, object[], object> CreateDelegateMethodInvoker(MethodInfo method)
|
|
1664
|
+
{
|
|
1665
|
+
try
|
|
1666
|
+
{
|
|
1667
|
+
// For IL2CPP/WebGL, focus on simple optimizations that avoid DynamicInvoke
|
|
1668
|
+
// which can be slower than direct reflection in some cases
|
|
1669
|
+
|
|
1670
|
+
ParameterInfo[] parameters = method.GetParameters();
|
|
1671
|
+
|
|
1672
|
+
// Only optimize very simple cases to avoid DynamicInvoke overhead
|
|
1673
|
+
if (parameters.Length == 0 && method.IsStatic)
|
|
1674
|
+
{
|
|
1675
|
+
if (method.ReturnType == typeof(void))
|
|
1676
|
+
{
|
|
1677
|
+
Action staticAction = (Action)
|
|
1678
|
+
Delegate.CreateDelegate(typeof(Action), method);
|
|
1679
|
+
return (instance, args) =>
|
|
1680
|
+
{
|
|
1681
|
+
staticAction();
|
|
1682
|
+
return null;
|
|
1683
|
+
};
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
if (method.ReturnType == typeof(int))
|
|
1687
|
+
{
|
|
1688
|
+
Func<int> staticFunc =
|
|
1689
|
+
(Func<int>)Delegate.CreateDelegate(typeof(Func<int>), method);
|
|
1690
|
+
return (instance, args) => staticFunc();
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
if (method.ReturnType == typeof(string))
|
|
1694
|
+
{
|
|
1695
|
+
Func<string> staticFunc =
|
|
1696
|
+
(Func<string>)Delegate.CreateDelegate(typeof(Func<string>), method);
|
|
1697
|
+
return (instance, args) => staticFunc();
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
if (method.ReturnType == typeof(bool))
|
|
1701
|
+
{
|
|
1702
|
+
Func<bool> staticFunc =
|
|
1703
|
+
(Func<bool>)Delegate.CreateDelegate(typeof(Func<bool>), method);
|
|
1704
|
+
return (instance, args) => staticFunc();
|
|
1705
|
+
}
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1708
|
+
// For most other cases, direct reflection is often faster than DynamicInvoke
|
|
1709
|
+
return null;
|
|
1710
|
+
}
|
|
1711
|
+
catch
|
|
1712
|
+
{
|
|
1713
|
+
return null; // Fallback to reflection
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
private static Func<object[], object> CreateDelegateStaticMethodInvoker(MethodInfo method)
|
|
1718
|
+
{
|
|
1719
|
+
try
|
|
1720
|
+
{
|
|
1721
|
+
ParameterInfo[] parameters = method.GetParameters();
|
|
1722
|
+
|
|
1723
|
+
// Only optimize simple static methods with no parameters to avoid DynamicInvoke
|
|
1724
|
+
if (parameters.Length == 0)
|
|
1725
|
+
{
|
|
1726
|
+
if (method.ReturnType == typeof(void))
|
|
1727
|
+
{
|
|
1728
|
+
Action action = (Action)Delegate.CreateDelegate(typeof(Action), method);
|
|
1729
|
+
return args =>
|
|
1730
|
+
{
|
|
1731
|
+
action();
|
|
1732
|
+
return null;
|
|
1733
|
+
};
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
if (method.ReturnType == typeof(int))
|
|
1737
|
+
{
|
|
1738
|
+
Func<int> func =
|
|
1739
|
+
(Func<int>)Delegate.CreateDelegate(typeof(Func<int>), method);
|
|
1740
|
+
return args => func();
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
if (method.ReturnType == typeof(string))
|
|
1744
|
+
{
|
|
1745
|
+
Func<string> func =
|
|
1746
|
+
(Func<string>)Delegate.CreateDelegate(typeof(Func<string>), method);
|
|
1747
|
+
return args => func();
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
if (method.ReturnType == typeof(bool))
|
|
1751
|
+
{
|
|
1752
|
+
Func<bool> func =
|
|
1753
|
+
(Func<bool>)Delegate.CreateDelegate(typeof(Func<bool>), method);
|
|
1754
|
+
return args => func();
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
// For other cases, reflection is often faster than DynamicInvoke
|
|
1759
|
+
return null;
|
|
1760
|
+
}
|
|
1761
|
+
catch
|
|
1762
|
+
{
|
|
1763
|
+
return null;
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
private static Func<object[], object> CreateDelegateConstructor(ConstructorInfo constructor)
|
|
1768
|
+
{
|
|
1769
|
+
try
|
|
1770
|
+
{
|
|
1771
|
+
ParameterInfo[] parameters = constructor.GetParameters();
|
|
1772
|
+
Type declaringType = constructor.DeclaringType;
|
|
1773
|
+
|
|
1774
|
+
// For constructors, we can use Activator.CreateInstance with optimizations
|
|
1775
|
+
// or create wrapper delegates that call the constructor
|
|
1776
|
+
|
|
1777
|
+
if (parameters.Length == 0)
|
|
1778
|
+
{
|
|
1779
|
+
// Use cached Activator.CreateInstance for parameterless constructors
|
|
1780
|
+
return args => Activator.CreateInstance(declaringType);
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
if (parameters.Length == 1)
|
|
1784
|
+
{
|
|
1785
|
+
Type paramType = parameters[0].ParameterType;
|
|
1786
|
+
return args => Activator.CreateInstance(declaringType, args[0]);
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
if (parameters.Length == 2)
|
|
1790
|
+
{
|
|
1791
|
+
return args => Activator.CreateInstance(declaringType, args[0], args[1]);
|
|
1792
|
+
}
|
|
1793
|
+
|
|
1794
|
+
if (parameters.Length <= 4)
|
|
1795
|
+
{
|
|
1796
|
+
// For up to 4 parameters, use Activator.CreateInstance which is reasonably fast
|
|
1797
|
+
return args => Activator.CreateInstance(declaringType, args);
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
// For more complex constructors, fallback to reflection
|
|
1801
|
+
return null;
|
|
1802
|
+
}
|
|
1803
|
+
catch
|
|
1804
|
+
{
|
|
1805
|
+
return null;
|
|
1806
|
+
}
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1809
|
+
private static Func<T> CreateDelegateParameterlessConstructor<T>(
|
|
1810
|
+
ConstructorInfo constructor
|
|
1811
|
+
)
|
|
1812
|
+
{
|
|
1813
|
+
try
|
|
1814
|
+
{
|
|
1815
|
+
// For parameterless constructors, we can use optimized Activator.CreateInstance
|
|
1816
|
+
if (constructor.GetParameters().Length == 0)
|
|
1817
|
+
{
|
|
1818
|
+
return () => (T)Activator.CreateInstance(typeof(T));
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
return null;
|
|
1822
|
+
}
|
|
1823
|
+
catch
|
|
1824
|
+
{
|
|
1825
|
+
return null;
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
private static Func<object, object> CreateDelegateFieldGetter(FieldInfo field)
|
|
1830
|
+
{
|
|
1831
|
+
try
|
|
1832
|
+
{
|
|
1833
|
+
if (field.IsStatic)
|
|
1834
|
+
{
|
|
1835
|
+
// For static fields, create a simple wrapper
|
|
1836
|
+
return instance => field.GetValue(null);
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1839
|
+
// For instance fields, we can't easily create delegates, so use optimized wrapper
|
|
1840
|
+
return instance => field.GetValue(instance);
|
|
1841
|
+
}
|
|
1842
|
+
catch
|
|
1843
|
+
{
|
|
1844
|
+
return null;
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
|
|
1848
|
+
private static Func<object, object> CreateDelegatePropertyGetter(PropertyInfo property)
|
|
1849
|
+
{
|
|
1850
|
+
try
|
|
1851
|
+
{
|
|
1852
|
+
MethodInfo getMethod = property.GetGetMethod(true);
|
|
1853
|
+
if (getMethod == null)
|
|
1854
|
+
{
|
|
1855
|
+
return null;
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
if (getMethod.IsStatic)
|
|
1859
|
+
{
|
|
1860
|
+
Type funcType = typeof(Func<>).MakeGenericType(property.PropertyType);
|
|
1861
|
+
Delegate getter = Delegate.CreateDelegate(funcType, getMethod);
|
|
1862
|
+
return instance => getter.DynamicInvoke();
|
|
1863
|
+
}
|
|
1864
|
+
else
|
|
1865
|
+
{
|
|
1866
|
+
Type funcType = typeof(Func<,>).MakeGenericType(
|
|
1867
|
+
property.DeclaringType,
|
|
1868
|
+
property.PropertyType
|
|
1869
|
+
);
|
|
1870
|
+
Delegate getter = Delegate.CreateDelegate(funcType, getMethod);
|
|
1871
|
+
return instance => getter.DynamicInvoke(instance);
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
catch
|
|
1875
|
+
{
|
|
1876
|
+
return null;
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
private static Func<object, object> CreateGenericFieldGetter(FieldInfo field)
|
|
1881
|
+
{
|
|
1882
|
+
try
|
|
1883
|
+
{
|
|
1884
|
+
// For now, just use direct field access - it's already reasonably fast
|
|
1885
|
+
if (field.IsStatic)
|
|
1886
|
+
{
|
|
1887
|
+
return instance => field.GetValue(null);
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1890
|
+
return instance => field.GetValue(instance);
|
|
1891
|
+
}
|
|
1892
|
+
catch
|
|
1893
|
+
{
|
|
1894
|
+
return null;
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
private static Type GetActionType(Type[] parameterTypes)
|
|
1899
|
+
{
|
|
1900
|
+
switch (parameterTypes.Length)
|
|
1901
|
+
{
|
|
1902
|
+
case 0:
|
|
1903
|
+
return typeof(Action);
|
|
1904
|
+
case 1:
|
|
1905
|
+
return typeof(Action<>).MakeGenericType(parameterTypes);
|
|
1906
|
+
case 2:
|
|
1907
|
+
return typeof(Action<,>).MakeGenericType(parameterTypes);
|
|
1908
|
+
case 3:
|
|
1909
|
+
return typeof(Action<,,>).MakeGenericType(parameterTypes);
|
|
1910
|
+
case 4:
|
|
1911
|
+
return typeof(Action<,,,>).MakeGenericType(parameterTypes);
|
|
1912
|
+
default:
|
|
1913
|
+
return null;
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
private static Type GetFuncType(Type[] typeArgs)
|
|
1918
|
+
{
|
|
1919
|
+
switch (typeArgs.Length)
|
|
1920
|
+
{
|
|
1921
|
+
case 1:
|
|
1922
|
+
return typeof(Func<>).MakeGenericType(typeArgs);
|
|
1923
|
+
case 2:
|
|
1924
|
+
return typeof(Func<,>).MakeGenericType(typeArgs);
|
|
1925
|
+
case 3:
|
|
1926
|
+
return typeof(Func<,,>).MakeGenericType(typeArgs);
|
|
1927
|
+
case 4:
|
|
1928
|
+
return typeof(Func<,,,>).MakeGenericType(typeArgs);
|
|
1929
|
+
case 5:
|
|
1930
|
+
return typeof(Func<,,,,>).MakeGenericType(typeArgs);
|
|
1931
|
+
default:
|
|
1932
|
+
return null;
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
589
1935
|
}
|
|
590
1936
|
}
|