com.wallstop-studios.unity-helpers 2.1.0 → 2.1.2
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.
- package/AGENTS.md +1 -0
- package/Docs/ILIST_SORTING_PERFORMANCE.md +92 -0
- package/{package-lock.json.meta → Docs/ILIST_SORTING_PERFORMANCE.md.meta} +1 -1
- package/Docs/INDEX.md +11 -1
- package/Docs/Images/random_generators.svg +7 -7
- package/Docs/RANDOM_PERFORMANCE.md +17 -14
- package/Docs/REFLECTION_HELPERS.md +84 -1
- package/Docs/REFLECTION_PERFORMANCE.md +169 -0
- package/Docs/REFLECTION_PERFORMANCE.md.meta +7 -0
- package/Docs/RELATIONAL_COMPONENTS.md +6 -0
- package/Docs/RELATIONAL_COMPONENT_PERFORMANCE.md +63 -0
- package/Docs/RELATIONAL_COMPONENT_PERFORMANCE.md.meta +7 -0
- package/Docs/SPATIAL_TREE_2D_PERFORMANCE.md +64 -64
- package/Docs/SPATIAL_TREE_3D_PERFORMANCE.md +64 -64
- package/Editor/Core/Helper/AnimationEventHelpers.cs +1 -1
- package/Editor/Sprites/AnimationCopier.cs +1 -1
- package/Editor/Sprites/AnimationViewerWindow.cs +4 -4
- package/Editor/Sprites/SpriteSettingsApplierAPI.cs +2 -1
- package/Editor/Sprites/TextureResizerWizard.cs +4 -3
- package/Editor/Utils/ScriptableObjectSingletonCreator.cs +3 -3
- package/README.md +33 -18
- package/Runtime/Core/Attributes/BaseRelationalComponentAttribute.cs +147 -20
- package/Runtime/Core/Attributes/ChildComponentAttribute.cs +630 -117
- package/Runtime/Core/Attributes/NotNullAttribute.cs +5 -2
- package/Runtime/Core/Attributes/ParentComponentAttribute.cs +477 -103
- package/Runtime/Core/Attributes/RelationalComponentAssigner.cs +26 -3
- package/Runtime/Core/Attributes/RelationalComponentExtensions.cs +19 -3
- package/Runtime/Core/Attributes/SiblingComponentAttribute.cs +265 -92
- package/Runtime/Core/CodeGen.meta +8 -0
- package/Runtime/Core/DataStructure/ImmutableBitSet.cs +5 -20
- package/Runtime/Core/Extension/IListExtensions.cs +720 -12
- package/Runtime/Core/Helper/Logging/UnityLogTagFormatter.cs +11 -7
- package/Runtime/Core/Helper/Objects.cs +1 -1
- package/Runtime/Core/Helper/ReflectionHelpers.Factory.cs +5142 -0
- package/Runtime/Core/Helper/ReflectionHelpers.Factory.cs.meta +11 -0
- package/Runtime/Core/Helper/ReflectionHelpers.cs +1812 -1518
- package/Runtime/Core/Helper/UnityMainThreadDispatcher.cs +2 -3
- package/Runtime/Core/Math/Line2D.cs +2 -4
- package/Runtime/Core/Math/Line3D.cs +2 -4
- package/Runtime/Core/Random/AbstractRandom.cs +52 -5
- package/Runtime/Core/Random/DotNetRandom.cs +3 -3
- package/Runtime/Core/Random/FlurryBurstRandom.cs +279 -0
- package/Runtime/Core/Random/FlurryBurstRandom.cs.meta +3 -0
- package/Runtime/Core/Random/IllusionFlow.cs +3 -3
- package/Runtime/Core/Random/LinearCongruentialGenerator.cs +3 -3
- package/Runtime/Core/Random/PcgRandom.cs +6 -6
- package/Runtime/Core/Random/PhotonSpinRandom.cs +387 -0
- package/Runtime/Core/Random/PhotonSpinRandom.cs.meta +3 -0
- package/Runtime/Core/Random/RomuDuo.cs +3 -3
- package/Runtime/Core/Random/SplitMix64.cs +3 -3
- package/Runtime/Core/Random/SquirrelRandom.cs +6 -4
- package/Runtime/Core/Random/StormDropRandom.cs +271 -0
- package/Runtime/Core/Random/StormDropRandom.cs.meta +3 -0
- package/Runtime/Core/Random/UnityRandom.cs +3 -3
- package/Runtime/Core/Random/WyRandom.cs +6 -4
- package/Runtime/Core/Random/XorShiftRandom.cs +3 -3
- package/Runtime/Core/Random/XoroShiroRandom.cs +3 -3
- package/Runtime/Tags/AttributeMetadataCache.cs +316 -9
- package/Runtime/Tags/CosmeticEffectData.cs +1 -1
- package/Runtime/Visuals/UIToolkit/MultiFileSelectorElement.cs +3 -3
- package/Tests/Editor/Helper/HelpersTests.cs +2 -2
- package/Tests/Editor/Helper/ReflectionHelpersTypedEditorTests.cs +87 -0
- package/Tests/Editor/Helper/ReflectionHelpersTypedEditorTests.cs.meta +11 -0
- package/Tests/Editor/Helper/SpriteHelpersTests.cs +1 -1
- package/Tests/Editor/PrefabCheckerReportTests.cs +3 -3
- package/Tests/Editor/Sprites/AnimationCopierFilterTests.cs +18 -12
- package/Tests/Editor/Sprites/AnimationCopierWindowTests.cs +8 -7
- package/Tests/Editor/Sprites/AnimationViewerWindowTests.cs +2 -1
- package/Tests/Editor/Sprites/ScriptableSpriteAtlasEditorTests.cs +6 -5
- package/Tests/Editor/Sprites/SpriteCropperAdditionalTests.cs +2 -1
- package/Tests/Editor/Sprites/SpriteCropperTests.cs +7 -6
- package/Tests/Editor/Sprites/SpritePivotAdjusterAdditionalTests.cs +2 -1
- package/Tests/Editor/Sprites/SpritePivotAdjusterTests.cs +4 -3
- package/Tests/Editor/Sprites/TextureResizerWizardTests.cs +10 -9
- package/Tests/Editor/Sprites/TextureSettingsApplierAPITests.cs +2 -1
- package/Tests/Editor/Tags/AttributeMetadataCacheTests.cs +192 -0
- package/Tests/Editor/Tags/AttributeMetadataCacheTests.cs.meta +11 -0
- package/Tests/Editor/Tags.meta +8 -0
- package/Tests/Runtime/Extensions/IListExtensionTests.cs +187 -1
- package/Tests/Runtime/Helper/ObjectsTests.cs +4 -4
- package/Tests/Runtime/Helper/ReflectionHelperCapabilityMatrixTests.cs +2923 -0
- package/Tests/Runtime/Helper/ReflectionHelperCapabilityMatrixTests.cs.meta +11 -0
- package/Tests/Runtime/Helper/ReflectionHelperTests.cs +660 -0
- package/Tests/Runtime/Integrations/Reflex/RelationalComponentsReflexTests.cs +2 -2
- package/Tests/Runtime/Performance/IListSortingPerformanceTests.cs +346 -0
- package/Tests/Runtime/Performance/IListSortingPerformanceTests.cs.meta +11 -0
- package/Tests/Runtime/Performance/RandomPerformanceTests.cs +3 -0
- package/Tests/Runtime/Performance/ReflectionPerformanceTests.cs +1238 -0
- package/Tests/Runtime/Performance/ReflectionPerformanceTests.cs.meta +11 -0
- package/Tests/Runtime/Performance/RelationalComponentBenchmarkTests.cs +832 -0
- package/Tests/Runtime/Performance/RelationalComponentBenchmarkTests.cs.meta +11 -0
- package/Tests/Runtime/Random/FlurryBurstRandomTests.cs +12 -0
- package/Tests/Runtime/Random/FlurryBurstRandomTests.cs.meta +3 -0
- package/Tests/Runtime/Random/PhotonSpinRandomTests.cs +12 -0
- package/Tests/Runtime/Random/PhotonSpinRandomTests.cs.meta +3 -0
- package/Tests/Runtime/Random/RandomProtoSerializationTests.cs +14 -0
- package/Tests/Runtime/Random/RandomTestBase.cs +39 -4
- package/Tests/Runtime/Random/StormDropRandomTests.cs +12 -0
- package/Tests/Runtime/Random/StormDropRandomTests.cs.meta +3 -0
- package/Tests/Runtime/Serialization/ProtoInterfaceResolutionEdgeTests.cs +2 -2
- package/Tests/Runtime/Serialization/ProtoRootRegistrationTests.cs +1 -1
- package/Tests/Runtime/Serialization/ProtoSerializeBehaviorTests.cs +1 -1
- package/Tests/Runtime/Tags/PeriodicEffectDefinitionSerializationTests.cs +2 -2
- package/package.json +1 -1
- package/Tests/Runtime/Performance/RelationComponentPerformanceTests.cs +0 -60
- package/Tests/Runtime/Performance/RelationComponentPerformanceTests.cs.meta +0 -3
|
@@ -48,7 +48,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
48
48
|
/// UnityEngine.Debug.Log(getter(p)); // 42
|
|
49
49
|
/// ]]></code>
|
|
50
50
|
/// </example>
|
|
51
|
-
public static class ReflectionHelpers
|
|
51
|
+
public static partial class ReflectionHelpers
|
|
52
52
|
{
|
|
53
53
|
// Cache for type resolution by name
|
|
54
54
|
#if !SINGLE_THREADED
|
|
@@ -66,54 +66,69 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
66
66
|
private static readonly Dictionary<Type, Func<int, IList>> ListWithCapacityCreators = new();
|
|
67
67
|
private static readonly Dictionary<Type, Func<int, object>> HashSetWithCapacityCreators =
|
|
68
68
|
new();
|
|
69
|
-
private static readonly Dictionary<
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
69
|
+
private static readonly Dictionary<Type, Action<object>> HashSetClearers = new();
|
|
70
|
+
|
|
71
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
72
|
+
private static Func<int, Array> GetArrayCreatorCached(Type type)
|
|
73
|
+
{
|
|
74
|
+
if (!ArrayCreators.TryGetValue(type, out Func<int, Array> factory))
|
|
75
|
+
{
|
|
76
|
+
factory = GetArrayCreator(type);
|
|
77
|
+
ArrayCreators[type] = factory;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return factory;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
84
|
+
private static Func<int, IList> GetListWithCapacityCreatorCached(Type elementType)
|
|
85
|
+
{
|
|
86
|
+
if (!ListWithCapacityCreators.TryGetValue(elementType, out Func<int, IList> factory))
|
|
87
|
+
{
|
|
88
|
+
factory = GetListWithCapacityCreator(elementType);
|
|
89
|
+
ListWithCapacityCreators[elementType] = factory;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return factory;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
96
|
+
private static Func<IList> GetListCreatorCached(Type elementType)
|
|
97
|
+
{
|
|
98
|
+
if (!ListCreators.TryGetValue(elementType, out Func<IList> factory))
|
|
99
|
+
{
|
|
100
|
+
factory = GetListCreator(elementType);
|
|
101
|
+
ListCreators[elementType] = factory;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return factory;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
108
|
+
private static Func<int, object> GetHashSetWithCapacityCreatorCached(Type elementType)
|
|
109
|
+
{
|
|
110
|
+
if (
|
|
111
|
+
!HashSetWithCapacityCreators.TryGetValue(elementType, out Func<int, object> factory)
|
|
112
|
+
)
|
|
113
|
+
{
|
|
114
|
+
factory = GetHashSetWithCapacityCreator(elementType);
|
|
115
|
+
HashSetWithCapacityCreators[elementType] = factory;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return factory;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
122
|
+
private static Action<object> GetHashSetClearerCached(Type elementType)
|
|
123
|
+
{
|
|
124
|
+
if (!HashSetClearers.TryGetValue(elementType, out Action<object> clearer))
|
|
125
|
+
{
|
|
126
|
+
clearer = GetHashSetClearer(elementType);
|
|
127
|
+
HashSetClearers[elementType] = clearer;
|
|
128
|
+
}
|
|
92
129
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedStaticInvoker0 = new();
|
|
96
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedStaticInvoker1 = new();
|
|
97
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedStaticInvoker3 = new();
|
|
98
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedStaticInvoker4 = new();
|
|
99
|
-
|
|
100
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedStaticAction0 = new();
|
|
101
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedStaticAction1 = new();
|
|
102
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedStaticAction2 = new();
|
|
103
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedStaticAction3 = new();
|
|
104
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedStaticAction4 = new();
|
|
105
|
-
|
|
106
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedInstanceInvoker0 = new();
|
|
107
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedInstanceInvoker1 = new();
|
|
108
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedInstanceInvoker2 = new();
|
|
109
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedInstanceInvoker3 = new();
|
|
110
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedInstanceInvoker4 = new();
|
|
111
|
-
|
|
112
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedInstanceAction0 = new();
|
|
113
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedInstanceAction1 = new();
|
|
114
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedInstanceAction2 = new();
|
|
115
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedInstanceAction3 = new();
|
|
116
|
-
private static readonly Dictionary<MethodInfo, Delegate> TypedInstanceAction4 = new();
|
|
130
|
+
return clearer;
|
|
131
|
+
}
|
|
117
132
|
#else
|
|
118
133
|
private static readonly ConcurrentDictionary<Type, Func<int, Array>> ArrayCreators = new();
|
|
119
134
|
private static readonly ConcurrentDictionary<Type, Func<IList>> ListCreators = new();
|
|
@@ -125,90 +140,91 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
125
140
|
Type,
|
|
126
141
|
Func<int, object>
|
|
127
142
|
> HashSetWithCapacityCreators = new();
|
|
128
|
-
private static readonly ConcurrentDictionary<
|
|
129
|
-
FieldInfo,
|
|
130
|
-
Func<object, object>
|
|
131
|
-
> FieldGetterCache = new();
|
|
132
|
-
private static readonly ConcurrentDictionary<
|
|
133
|
-
FieldInfo,
|
|
134
|
-
Action<object, object>
|
|
135
|
-
> FieldSetterCache = new();
|
|
136
|
-
private static readonly ConcurrentDictionary<
|
|
137
|
-
FieldInfo,
|
|
138
|
-
Func<object>
|
|
139
|
-
> StaticFieldGetterCache = new();
|
|
140
|
-
private static readonly ConcurrentDictionary<
|
|
141
|
-
FieldInfo,
|
|
142
|
-
Action<object>
|
|
143
|
-
> StaticFieldSetterCache = new();
|
|
144
|
-
private static readonly ConcurrentDictionary<
|
|
145
|
-
PropertyInfo,
|
|
146
|
-
Func<object, object>
|
|
147
|
-
> PropertyGetterCache = new();
|
|
148
|
-
private static readonly ConcurrentDictionary<
|
|
149
|
-
PropertyInfo,
|
|
150
|
-
Action<object, object>
|
|
151
|
-
> PropertySetterCache = new();
|
|
152
|
-
private static readonly ConcurrentDictionary<
|
|
153
|
-
MethodInfo,
|
|
154
|
-
Func<object, object[], object>
|
|
155
|
-
> MethodInvokers = new();
|
|
156
|
-
private static readonly ConcurrentDictionary<
|
|
157
|
-
MethodInfo,
|
|
158
|
-
Func<object[], object>
|
|
159
|
-
> StaticMethodInvokers = new();
|
|
160
|
-
private static readonly ConcurrentDictionary<
|
|
161
|
-
ConstructorInfo,
|
|
162
|
-
Func<object[], object>
|
|
163
|
-
> Constructors = new();
|
|
143
|
+
private static readonly ConcurrentDictionary<Type, Action<object>> HashSetClearers = new();
|
|
164
144
|
|
|
165
|
-
|
|
166
|
-
private static
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
private static readonly ConcurrentDictionary<MethodInfo, Delegate> TypedStaticInvoker1 =
|
|
171
|
-
new();
|
|
172
|
-
private static readonly ConcurrentDictionary<MethodInfo, Delegate> TypedStaticInvoker3 =
|
|
173
|
-
new();
|
|
174
|
-
private static readonly ConcurrentDictionary<MethodInfo, Delegate> TypedStaticInvoker4 =
|
|
175
|
-
new();
|
|
145
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
146
|
+
private static Func<int, Array> GetArrayCreatorCached(Type type)
|
|
147
|
+
{
|
|
148
|
+
return ArrayCreators.GetOrAdd(type, static elementType => GetArrayCreator(elementType));
|
|
149
|
+
}
|
|
176
150
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
private static readonly ConcurrentDictionary<MethodInfo, Delegate> TypedStaticAction4 =
|
|
186
|
-
new();
|
|
151
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
152
|
+
private static Func<int, IList> GetListWithCapacityCreatorCached(Type elementType)
|
|
153
|
+
{
|
|
154
|
+
return ListWithCapacityCreators.GetOrAdd(
|
|
155
|
+
elementType,
|
|
156
|
+
static type => GetListWithCapacityCreator(type)
|
|
157
|
+
);
|
|
158
|
+
}
|
|
187
159
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
new();
|
|
194
|
-
private static readonly ConcurrentDictionary<MethodInfo, Delegate> TypedInstanceInvoker3 =
|
|
195
|
-
new();
|
|
196
|
-
private static readonly ConcurrentDictionary<MethodInfo, Delegate> TypedInstanceInvoker4 =
|
|
197
|
-
new();
|
|
160
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
161
|
+
private static Func<IList> GetListCreatorCached(Type elementType)
|
|
162
|
+
{
|
|
163
|
+
return ListCreators.GetOrAdd(elementType, static type => GetListCreator(type));
|
|
164
|
+
}
|
|
198
165
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
166
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
167
|
+
private static Func<int, object> GetHashSetWithCapacityCreatorCached(Type elementType)
|
|
168
|
+
{
|
|
169
|
+
return HashSetWithCapacityCreators.GetOrAdd(
|
|
170
|
+
elementType,
|
|
171
|
+
static type => GetHashSetWithCapacityCreator(type)
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
176
|
+
private static Action<object> GetHashSetClearerCached(Type elementType)
|
|
177
|
+
{
|
|
178
|
+
return HashSetClearers.GetOrAdd(elementType, static type => GetHashSetClearer(type));
|
|
179
|
+
}
|
|
209
180
|
#endif
|
|
210
181
|
|
|
211
182
|
private static readonly bool CanCompileExpressions = CheckExpressionCompilationSupport();
|
|
183
|
+
private static readonly bool DynamicIlSupported = CheckDynamicIlSupport();
|
|
184
|
+
private static bool? _ExpressionCapabilityOverride;
|
|
185
|
+
private static bool? _DynamicIlCapabilityOverride;
|
|
186
|
+
|
|
187
|
+
internal static bool ExpressionsEnabled =>
|
|
188
|
+
_ExpressionCapabilityOverride ?? CanCompileExpressions;
|
|
189
|
+
|
|
190
|
+
internal static bool DynamicIlEnabled => _DynamicIlCapabilityOverride ?? DynamicIlSupported;
|
|
191
|
+
|
|
192
|
+
internal static IDisposable OverrideReflectionCapabilities(
|
|
193
|
+
bool? expressions,
|
|
194
|
+
bool? dynamicIl
|
|
195
|
+
)
|
|
196
|
+
{
|
|
197
|
+
bool? previousExpressions = _ExpressionCapabilityOverride;
|
|
198
|
+
bool? previousDynamicIl = _DynamicIlCapabilityOverride;
|
|
199
|
+
_ExpressionCapabilityOverride = expressions;
|
|
200
|
+
_DynamicIlCapabilityOverride = dynamicIl;
|
|
201
|
+
return new CapabilityOverrideScope(previousExpressions, previousDynamicIl);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private sealed class CapabilityOverrideScope : IDisposable
|
|
205
|
+
{
|
|
206
|
+
private readonly bool? _previousExpressions;
|
|
207
|
+
private readonly bool? _previousDynamicIl;
|
|
208
|
+
private bool _disposed;
|
|
209
|
+
|
|
210
|
+
internal CapabilityOverrideScope(bool? expressions, bool? dynamicIl)
|
|
211
|
+
{
|
|
212
|
+
_previousExpressions = expressions;
|
|
213
|
+
_previousDynamicIl = dynamicIl;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
public void Dispose()
|
|
217
|
+
{
|
|
218
|
+
if (_disposed)
|
|
219
|
+
{
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
_ExpressionCapabilityOverride = _previousExpressions;
|
|
224
|
+
_DynamicIlCapabilityOverride = _previousDynamicIl;
|
|
225
|
+
_disposed = true;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
212
228
|
|
|
213
229
|
#if SINGLE_THREADED
|
|
214
230
|
private static readonly Dictionary<
|
|
@@ -335,7 +351,6 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
335
351
|
);
|
|
336
352
|
}
|
|
337
353
|
|
|
338
|
-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
339
354
|
/// <summary>
|
|
340
355
|
/// Creates a new array instance of element <paramref name="type"/> with the specified length.
|
|
341
356
|
/// </summary>
|
|
@@ -344,15 +359,12 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
344
359
|
/// Array ints = ReflectionHelpers.CreateArray(typeof(int), 16); // int[16]
|
|
345
360
|
/// ]]></code>
|
|
346
361
|
/// </example>
|
|
362
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
347
363
|
public static Array CreateArray(Type type, int length)
|
|
348
364
|
{
|
|
349
|
-
return
|
|
350
|
-
// ReSharper disable once ConvertClosureToMethodGroup
|
|
351
|
-
.GetOrAdd(type, elementType => GetArrayCreator(elementType))
|
|
352
|
-
.Invoke(length);
|
|
365
|
+
return GetArrayCreatorCached(type).Invoke(length);
|
|
353
366
|
}
|
|
354
367
|
|
|
355
|
-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
356
368
|
/// <summary>
|
|
357
369
|
/// Creates a new <see cref="List{T}"/> instance for <paramref name="elementType"/> with the specified capacity.
|
|
358
370
|
/// </summary>
|
|
@@ -361,15 +373,12 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
361
373
|
/// IList list = ReflectionHelpers.CreateList(typeof(string), 128); // List<string> with Capacity=128
|
|
362
374
|
/// ]]></code>
|
|
363
375
|
/// </example>
|
|
376
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
364
377
|
public static IList CreateList(Type elementType, int length)
|
|
365
378
|
{
|
|
366
|
-
return
|
|
367
|
-
// ReSharper disable once ConvertClosureToMethodGroup
|
|
368
|
-
.GetOrAdd(elementType, type => GetListWithCapacityCreator(type))
|
|
369
|
-
.Invoke(length);
|
|
379
|
+
return GetListWithCapacityCreatorCached(elementType).Invoke(length);
|
|
370
380
|
}
|
|
371
381
|
|
|
372
|
-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
373
382
|
/// <summary>
|
|
374
383
|
/// Creates a new <see cref="List{T}"/> instance for <paramref name="elementType"/>.
|
|
375
384
|
/// </summary>
|
|
@@ -378,21 +387,54 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
378
387
|
/// IList list = ReflectionHelpers.CreateList(typeof(UnityEngine.Vector3));
|
|
379
388
|
/// ]]></code>
|
|
380
389
|
/// </example>
|
|
390
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
381
391
|
public static IList CreateList(Type elementType)
|
|
382
392
|
{
|
|
383
|
-
|
|
384
|
-
return ListCreators.GetOrAdd(elementType, type => GetListCreator(type)).Invoke();
|
|
393
|
+
return GetListCreatorCached(elementType).Invoke();
|
|
385
394
|
}
|
|
386
395
|
|
|
387
396
|
// Test helpers to avoid reflection in tests when asserting cache state
|
|
388
397
|
internal static bool IsFieldGetterCached(FieldInfo field)
|
|
389
398
|
{
|
|
390
|
-
return
|
|
399
|
+
return DelegateFactory.IsFieldGetterCached(field);
|
|
391
400
|
}
|
|
392
401
|
|
|
393
402
|
internal static bool IsFieldSetterCached(FieldInfo field)
|
|
394
403
|
{
|
|
395
|
-
return
|
|
404
|
+
return DelegateFactory.IsFieldSetterCached(field);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
internal static void ClearFieldGetterCache()
|
|
408
|
+
{
|
|
409
|
+
DelegateFactory.ClearFieldGetterCache();
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
internal static void ClearFieldSetterCache()
|
|
413
|
+
{
|
|
414
|
+
DelegateFactory.ClearFieldSetterCache();
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
internal static void ClearPropertyCache()
|
|
418
|
+
{
|
|
419
|
+
DelegateFactory.ClearPropertyCache();
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
internal static void ClearMethodCache()
|
|
423
|
+
{
|
|
424
|
+
DelegateFactory.ClearMethodCache();
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
internal static void ClearConstructorCache()
|
|
428
|
+
{
|
|
429
|
+
DelegateFactory.ClearConstructorCache();
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
internal static bool TryGetDelegateStrategy(
|
|
433
|
+
Delegate delegateInstance,
|
|
434
|
+
out ReflectionDelegateStrategy strategy
|
|
435
|
+
)
|
|
436
|
+
{
|
|
437
|
+
return DelegateFactory.TryGetStrategy(delegateInstance, out strategy);
|
|
396
438
|
}
|
|
397
439
|
|
|
398
440
|
/// <summary>
|
|
@@ -410,13 +452,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
410
452
|
/// </example>
|
|
411
453
|
public static Func<object, object> GetFieldGetter(FieldInfo field)
|
|
412
454
|
{
|
|
413
|
-
return
|
|
414
|
-
#if !EMIT_DYNAMIC_IL
|
|
415
|
-
CreateCompiledFieldGetter(f)
|
|
416
|
-
#else
|
|
417
|
-
BuildFieldGetterIL(f)
|
|
418
|
-
#endif
|
|
419
|
-
);
|
|
455
|
+
return DelegateFactory.GetFieldGetter(field);
|
|
420
456
|
}
|
|
421
457
|
|
|
422
458
|
#if EMIT_DYNAMIC_IL
|
|
@@ -465,13 +501,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
465
501
|
/// </example>
|
|
466
502
|
public static Func<object, object> GetPropertyGetter(PropertyInfo property)
|
|
467
503
|
{
|
|
468
|
-
return
|
|
469
|
-
#if !EMIT_DYNAMIC_IL
|
|
470
|
-
CreateCompiledPropertyGetter(p)
|
|
471
|
-
#else
|
|
472
|
-
BuildPropertyGetterIL(p)
|
|
473
|
-
#endif
|
|
474
|
-
);
|
|
504
|
+
return DelegateFactory.GetPropertyGetter(property);
|
|
475
505
|
}
|
|
476
506
|
|
|
477
507
|
#if EMIT_DYNAMIC_IL
|
|
@@ -537,84 +567,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
537
567
|
PropertyInfo property
|
|
538
568
|
)
|
|
539
569
|
{
|
|
540
|
-
|
|
541
|
-
return Getter;
|
|
542
|
-
TValue Getter(TInstance instance)
|
|
543
|
-
{
|
|
544
|
-
return (TValue)property.GetValue(instance);
|
|
545
|
-
}
|
|
546
|
-
#else
|
|
547
|
-
MethodInfo getMethod = property.GetGetMethod(true);
|
|
548
|
-
if (getMethod == null)
|
|
549
|
-
{
|
|
550
|
-
throw new ArgumentException(
|
|
551
|
-
$"Property {property.Name} has no getter",
|
|
552
|
-
nameof(property)
|
|
553
|
-
);
|
|
554
|
-
}
|
|
555
|
-
|
|
556
|
-
DynamicMethod dynamicMethod = new(
|
|
557
|
-
$"GetGeneric{property.DeclaringType.Name}_{property.Name}",
|
|
558
|
-
typeof(TValue),
|
|
559
|
-
new[] { typeof(TInstance) },
|
|
560
|
-
property.DeclaringType,
|
|
561
|
-
true
|
|
562
|
-
);
|
|
563
|
-
|
|
564
|
-
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
565
|
-
|
|
566
|
-
if (getMethod.IsStatic)
|
|
567
|
-
{
|
|
568
|
-
il.Emit(OpCodes.Call, getMethod);
|
|
569
|
-
}
|
|
570
|
-
else
|
|
571
|
-
{
|
|
572
|
-
if (typeof(TInstance).IsValueType)
|
|
573
|
-
{
|
|
574
|
-
il.Emit(OpCodes.Ldarga_S, 0);
|
|
575
|
-
}
|
|
576
|
-
else
|
|
577
|
-
{
|
|
578
|
-
il.Emit(OpCodes.Ldarg_0);
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
if (property.DeclaringType != typeof(TInstance))
|
|
582
|
-
{
|
|
583
|
-
il.Emit(
|
|
584
|
-
property.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
|
|
585
|
-
property.DeclaringType
|
|
586
|
-
);
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
il.Emit(
|
|
590
|
-
property.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt,
|
|
591
|
-
getMethod
|
|
592
|
-
);
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
if (property.PropertyType.IsValueType)
|
|
596
|
-
{
|
|
597
|
-
if (!typeof(TValue).IsValueType)
|
|
598
|
-
{
|
|
599
|
-
il.Emit(OpCodes.Box, property.PropertyType);
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
else
|
|
603
|
-
{
|
|
604
|
-
if (typeof(TValue).IsValueType)
|
|
605
|
-
{
|
|
606
|
-
il.Emit(OpCodes.Unbox_Any, typeof(TValue));
|
|
607
|
-
}
|
|
608
|
-
else if (typeof(TValue) != property.PropertyType)
|
|
609
|
-
{
|
|
610
|
-
il.Emit(OpCodes.Castclass, typeof(TValue));
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
il.Emit(OpCodes.Ret);
|
|
615
|
-
return (Func<TInstance, TValue>)
|
|
616
|
-
dynamicMethod.CreateDelegate(typeof(Func<TInstance, TValue>));
|
|
617
|
-
#endif
|
|
570
|
+
return DelegateFactory.GetPropertyGetterTyped<TInstance, TValue>(property);
|
|
618
571
|
}
|
|
619
572
|
|
|
620
573
|
/// <summary>
|
|
@@ -641,13 +594,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
641
594
|
nameof(property)
|
|
642
595
|
);
|
|
643
596
|
}
|
|
644
|
-
return
|
|
645
|
-
#if !EMIT_DYNAMIC_IL
|
|
646
|
-
((obj, value) => p.SetValue(obj, value))
|
|
647
|
-
#else
|
|
648
|
-
BuildPropertySetterIL(p)
|
|
649
|
-
#endif
|
|
650
|
-
);
|
|
597
|
+
return DelegateFactory.GetPropertySetter(property);
|
|
651
598
|
}
|
|
652
599
|
|
|
653
600
|
public static Action<TInstance, TValue> GetPropertySetter<TInstance, TValue>(
|
|
@@ -662,106 +609,25 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
662
609
|
nameof(property)
|
|
663
610
|
);
|
|
664
611
|
}
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
#else
|
|
668
|
-
DynamicMethod dynamicMethod = new(
|
|
669
|
-
$"SetPropertyGeneric{property.DeclaringType.Name}_{property.Name}",
|
|
670
|
-
typeof(void),
|
|
671
|
-
new[] { typeof(TInstance), typeof(TValue) },
|
|
672
|
-
property.DeclaringType,
|
|
673
|
-
true
|
|
674
|
-
);
|
|
675
|
-
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
612
|
+
return DelegateFactory.GetPropertySetterTyped<TInstance, TValue>(property);
|
|
613
|
+
}
|
|
676
614
|
|
|
677
|
-
|
|
615
|
+
public static Action<TValue> GetStaticPropertySetter<TValue>(PropertyInfo property)
|
|
616
|
+
{
|
|
617
|
+
MethodInfo setMethod = property.GetSetMethod(true);
|
|
618
|
+
if (setMethod == null || !setMethod.IsStatic)
|
|
678
619
|
{
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
property.PropertyType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass,
|
|
684
|
-
property.PropertyType
|
|
685
|
-
);
|
|
686
|
-
}
|
|
687
|
-
il.Emit(OpCodes.Call, setMethod);
|
|
620
|
+
throw new ArgumentException(
|
|
621
|
+
$"Property {property?.Name} must be static and have a setter",
|
|
622
|
+
nameof(property)
|
|
623
|
+
);
|
|
688
624
|
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
else
|
|
696
|
-
{
|
|
697
|
-
il.Emit(OpCodes.Ldarg_0);
|
|
698
|
-
}
|
|
699
|
-
if (property.DeclaringType != typeof(TInstance))
|
|
700
|
-
{
|
|
701
|
-
il.Emit(
|
|
702
|
-
property.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
|
|
703
|
-
property.DeclaringType
|
|
704
|
-
);
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
il.Emit(OpCodes.Ldarg_1);
|
|
708
|
-
if (property.PropertyType != typeof(TValue))
|
|
709
|
-
{
|
|
710
|
-
il.Emit(
|
|
711
|
-
property.PropertyType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass,
|
|
712
|
-
property.PropertyType
|
|
713
|
-
);
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
il.Emit(
|
|
717
|
-
property.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt,
|
|
718
|
-
setMethod
|
|
719
|
-
);
|
|
720
|
-
}
|
|
721
|
-
il.Emit(OpCodes.Ret);
|
|
722
|
-
return (Action<TInstance, TValue>)
|
|
723
|
-
dynamicMethod.CreateDelegate(typeof(Action<TInstance, TValue>));
|
|
724
|
-
#endif
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
public static Action<TValue> GetStaticPropertySetter<TValue>(PropertyInfo property)
|
|
728
|
-
{
|
|
729
|
-
MethodInfo setMethod = property.GetSetMethod(true);
|
|
730
|
-
if (setMethod == null || !setMethod.IsStatic)
|
|
731
|
-
{
|
|
732
|
-
throw new ArgumentException(
|
|
733
|
-
$"Property {property?.Name} must be static and have a setter",
|
|
734
|
-
nameof(property)
|
|
735
|
-
);
|
|
736
|
-
}
|
|
737
|
-
#if !EMIT_DYNAMIC_IL
|
|
738
|
-
return value => property.SetValue(null, value);
|
|
739
|
-
#else
|
|
740
|
-
DynamicMethod dynamicMethod = new(
|
|
741
|
-
$"SetStaticProperty_{property.DeclaringType.Name}_{property.Name}",
|
|
742
|
-
typeof(void),
|
|
743
|
-
new[] { typeof(TValue) },
|
|
744
|
-
property.DeclaringType,
|
|
745
|
-
true
|
|
746
|
-
);
|
|
747
|
-
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
748
|
-
il.Emit(OpCodes.Ldarg_0);
|
|
749
|
-
if (property.PropertyType != typeof(TValue))
|
|
750
|
-
{
|
|
751
|
-
il.Emit(
|
|
752
|
-
property.PropertyType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass,
|
|
753
|
-
property.PropertyType
|
|
754
|
-
);
|
|
755
|
-
}
|
|
756
|
-
il.Emit(OpCodes.Call, setMethod);
|
|
757
|
-
il.Emit(OpCodes.Ret);
|
|
758
|
-
return (Action<TValue>)dynamicMethod.CreateDelegate(typeof(Action<TValue>));
|
|
759
|
-
#endif
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
public static Func<object, object[], object> GetIndexerGetter(PropertyInfo property)
|
|
763
|
-
{
|
|
764
|
-
if (property == null)
|
|
625
|
+
return DelegateFactory.GetStaticPropertySetterTyped<TValue>(property);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
public static Func<object, object[], object> GetIndexerGetter(PropertyInfo property)
|
|
629
|
+
{
|
|
630
|
+
if (property == null)
|
|
765
631
|
{
|
|
766
632
|
throw new ArgumentNullException(nameof(property));
|
|
767
633
|
}
|
|
@@ -770,80 +636,12 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
770
636
|
{
|
|
771
637
|
throw new ArgumentException("Property is not an indexer", nameof(property));
|
|
772
638
|
}
|
|
773
|
-
#if !EMIT_DYNAMIC_IL
|
|
774
|
-
if (!CanCompileExpressions)
|
|
775
|
-
{
|
|
776
|
-
return (instance, indexArgs) =>
|
|
777
|
-
{
|
|
778
|
-
if (indexArgs == null || indexArgs.Length != indices.Length)
|
|
779
|
-
{
|
|
780
|
-
throw new IndexOutOfRangeException(
|
|
781
|
-
$"Indexer expects {indices.Length} index argument(s); received {(indexArgs == null ? 0 : indexArgs.Length)}."
|
|
782
|
-
);
|
|
783
|
-
}
|
|
784
|
-
return property.GetValue(instance, indexArgs);
|
|
785
|
-
};
|
|
786
|
-
}
|
|
787
|
-
ParameterExpression inst = Expression.Parameter(typeof(object), "instance");
|
|
788
|
-
ParameterExpression args = Expression.Parameter(typeof(object[]), "args");
|
|
789
|
-
Expression target = property.DeclaringType.IsValueType
|
|
790
|
-
? Expression.Unbox(inst, property.DeclaringType)
|
|
791
|
-
: Expression.Convert(inst, property.DeclaringType);
|
|
792
|
-
UnaryExpression[] indexExprs = indices
|
|
793
|
-
.Select(
|
|
794
|
-
(p, i) =>
|
|
795
|
-
p.ParameterType.IsValueType
|
|
796
|
-
? Expression.Unbox(
|
|
797
|
-
Expression.ArrayIndex(args, Expression.Constant(i)),
|
|
798
|
-
p.ParameterType
|
|
799
|
-
)
|
|
800
|
-
: Expression.Convert(
|
|
801
|
-
Expression.ArrayIndex(args, Expression.Constant(i)),
|
|
802
|
-
p.ParameterType
|
|
803
|
-
)
|
|
804
|
-
)
|
|
805
|
-
.ToArray();
|
|
806
|
-
Expression call = Expression.Property(target, property, indexExprs);
|
|
807
|
-
Expression ret = property.PropertyType.IsValueType
|
|
808
|
-
? Expression.Convert(call, typeof(object))
|
|
809
|
-
: call;
|
|
810
|
-
return Expression.Lambda<Func<object, object[], object>>(ret, inst, args).Compile();
|
|
811
|
-
#else
|
|
812
639
|
MethodInfo getter = property.GetGetMethod(true);
|
|
813
640
|
if (getter == null)
|
|
814
641
|
{
|
|
815
642
|
throw new ArgumentException("Indexer has no getter", nameof(property));
|
|
816
643
|
}
|
|
817
|
-
|
|
818
|
-
$"GetIndexer_{property.DeclaringType.Name}_{property.Name}",
|
|
819
|
-
typeof(object),
|
|
820
|
-
new[] { typeof(object), typeof(object[]) },
|
|
821
|
-
property.DeclaringType,
|
|
822
|
-
true
|
|
823
|
-
);
|
|
824
|
-
ILGenerator il = dm.GetILGenerator();
|
|
825
|
-
il.Emit(OpCodes.Ldarg_0);
|
|
826
|
-
il.Emit(
|
|
827
|
-
property.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
|
|
828
|
-
property.DeclaringType
|
|
829
|
-
);
|
|
830
|
-
for (int i = 0; i < indices.Length; i++)
|
|
831
|
-
{
|
|
832
|
-
il.Emit(OpCodes.Ldarg_1);
|
|
833
|
-
il.Emit(OpCodes.Ldc_I4, i);
|
|
834
|
-
il.Emit(OpCodes.Ldelem_Ref);
|
|
835
|
-
Type pt = indices[i].ParameterType;
|
|
836
|
-
il.Emit(pt.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, pt);
|
|
837
|
-
}
|
|
838
|
-
il.Emit(property.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt, getter);
|
|
839
|
-
if (property.PropertyType.IsValueType)
|
|
840
|
-
{
|
|
841
|
-
il.Emit(OpCodes.Box, property.PropertyType);
|
|
842
|
-
}
|
|
843
|
-
il.Emit(OpCodes.Ret);
|
|
844
|
-
return (Func<object, object[], object>)
|
|
845
|
-
dm.CreateDelegate(typeof(Func<object, object[], object>));
|
|
846
|
-
#endif
|
|
644
|
+
return DelegateFactory.GetIndexerGetter(property);
|
|
847
645
|
}
|
|
848
646
|
|
|
849
647
|
public static Action<object, object, object[]> GetIndexerSetter(PropertyInfo property)
|
|
@@ -862,100 +660,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
862
660
|
{
|
|
863
661
|
throw new ArgumentException("Indexer has no setter", nameof(property));
|
|
864
662
|
}
|
|
865
|
-
|
|
866
|
-
if (!CanCompileExpressions)
|
|
867
|
-
{
|
|
868
|
-
return (instance, value, indexArgs) =>
|
|
869
|
-
{
|
|
870
|
-
if (indexArgs == null || indexArgs.Length != indices.Length)
|
|
871
|
-
{
|
|
872
|
-
throw new IndexOutOfRangeException(
|
|
873
|
-
$"Indexer expects {indices.Length} index argument(s); received {(indexArgs == null ? 0 : indexArgs.Length)}."
|
|
874
|
-
);
|
|
875
|
-
}
|
|
876
|
-
// Validate index argument types to mirror IL/unbox behavior
|
|
877
|
-
for (int i = 0; i < indices.Length; i++)
|
|
878
|
-
{
|
|
879
|
-
object idxVal = indexArgs[i];
|
|
880
|
-
Type pt = indices[i].ParameterType;
|
|
881
|
-
if (idxVal == null)
|
|
882
|
-
{
|
|
883
|
-
if (pt.IsValueType && Nullable.GetUnderlyingType(pt) == null)
|
|
884
|
-
{
|
|
885
|
-
throw new InvalidCastException(
|
|
886
|
-
$"Object of type 'null' cannot be converted to type '{pt}'."
|
|
887
|
-
);
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
else if (!pt.IsInstanceOfType(idxVal))
|
|
891
|
-
{
|
|
892
|
-
throw new InvalidCastException(
|
|
893
|
-
$"Object of type '{idxVal.GetType()}' cannot be converted to type '{pt}'."
|
|
894
|
-
);
|
|
895
|
-
}
|
|
896
|
-
}
|
|
897
|
-
property.SetValue(instance, value, indexArgs);
|
|
898
|
-
};
|
|
899
|
-
}
|
|
900
|
-
ParameterExpression inst = Expression.Parameter(typeof(object), "instance");
|
|
901
|
-
ParameterExpression value = Expression.Parameter(typeof(object), "value");
|
|
902
|
-
ParameterExpression args = Expression.Parameter(typeof(object[]), "args");
|
|
903
|
-
Expression target = property.DeclaringType.IsValueType
|
|
904
|
-
? Expression.Unbox(inst, property.DeclaringType)
|
|
905
|
-
: Expression.Convert(inst, property.DeclaringType);
|
|
906
|
-
UnaryExpression[] indexExprs = indices
|
|
907
|
-
.Select(
|
|
908
|
-
(p, i) =>
|
|
909
|
-
p.ParameterType.IsValueType
|
|
910
|
-
? Expression.Unbox(
|
|
911
|
-
Expression.ArrayIndex(args, Expression.Constant(i)),
|
|
912
|
-
p.ParameterType
|
|
913
|
-
)
|
|
914
|
-
: Expression.Convert(
|
|
915
|
-
Expression.ArrayIndex(args, Expression.Constant(i)),
|
|
916
|
-
p.ParameterType
|
|
917
|
-
)
|
|
918
|
-
)
|
|
919
|
-
.ToArray();
|
|
920
|
-
Expression valExpr = property.PropertyType.IsValueType
|
|
921
|
-
? Expression.Unbox(value, property.PropertyType)
|
|
922
|
-
: Expression.Convert(value, property.PropertyType);
|
|
923
|
-
Expression call = Expression.Call(target, setter, indexExprs.Append(valExpr));
|
|
924
|
-
return Expression
|
|
925
|
-
.Lambda<Action<object, object, object[]>>(call, inst, value, args)
|
|
926
|
-
.Compile();
|
|
927
|
-
#else
|
|
928
|
-
DynamicMethod dm = new(
|
|
929
|
-
$"SetIndexer_{property.DeclaringType.Name}_{property.Name}",
|
|
930
|
-
typeof(void),
|
|
931
|
-
new[] { typeof(object), typeof(object), typeof(object[]) },
|
|
932
|
-
property.DeclaringType,
|
|
933
|
-
true
|
|
934
|
-
);
|
|
935
|
-
ILGenerator il = dm.GetILGenerator();
|
|
936
|
-
il.Emit(OpCodes.Ldarg_0);
|
|
937
|
-
il.Emit(
|
|
938
|
-
property.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
|
|
939
|
-
property.DeclaringType
|
|
940
|
-
);
|
|
941
|
-
for (int i = 0; i < indices.Length; i++)
|
|
942
|
-
{
|
|
943
|
-
il.Emit(OpCodes.Ldarg_2);
|
|
944
|
-
il.Emit(OpCodes.Ldc_I4, i);
|
|
945
|
-
il.Emit(OpCodes.Ldelem_Ref);
|
|
946
|
-
Type pt = indices[i].ParameterType;
|
|
947
|
-
il.Emit(pt.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass, pt);
|
|
948
|
-
}
|
|
949
|
-
il.Emit(OpCodes.Ldarg_1);
|
|
950
|
-
il.Emit(
|
|
951
|
-
property.PropertyType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass,
|
|
952
|
-
property.PropertyType
|
|
953
|
-
);
|
|
954
|
-
il.Emit(property.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt, setter);
|
|
955
|
-
il.Emit(OpCodes.Ret);
|
|
956
|
-
return (Action<object, object, object[]>)
|
|
957
|
-
dm.CreateDelegate(typeof(Action<object, object, object[]>));
|
|
958
|
-
#endif
|
|
663
|
+
return DelegateFactory.GetIndexerSetter(property);
|
|
959
664
|
}
|
|
960
665
|
|
|
961
666
|
#if EMIT_DYNAMIC_IL
|
|
@@ -1033,25 +738,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1033
738
|
$"Type {type.FullName} does not have a parameterless constructor"
|
|
1034
739
|
);
|
|
1035
740
|
}
|
|
1036
|
-
|
|
1037
|
-
return () => Activator.CreateInstance(type);
|
|
1038
|
-
#else
|
|
1039
|
-
DynamicMethod dynamicMethod = new(
|
|
1040
|
-
$"New_{type.Name}",
|
|
1041
|
-
typeof(object),
|
|
1042
|
-
Type.EmptyTypes,
|
|
1043
|
-
type,
|
|
1044
|
-
true
|
|
1045
|
-
);
|
|
1046
|
-
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
1047
|
-
il.Emit(OpCodes.Newobj, ctor);
|
|
1048
|
-
if (type.IsValueType)
|
|
1049
|
-
{
|
|
1050
|
-
il.Emit(OpCodes.Box, type);
|
|
1051
|
-
}
|
|
1052
|
-
il.Emit(OpCodes.Ret);
|
|
1053
|
-
return (Func<object>)dynamicMethod.CreateDelegate(typeof(Func<object>));
|
|
1054
|
-
#endif
|
|
741
|
+
return DelegateFactory.GetParameterlessConstructor(ctor);
|
|
1055
742
|
}
|
|
1056
743
|
|
|
1057
744
|
/// <summary>
|
|
@@ -1066,13 +753,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1066
753
|
{
|
|
1067
754
|
throw new ArgumentException(nameof(field));
|
|
1068
755
|
}
|
|
1069
|
-
return
|
|
1070
|
-
#if !EMIT_DYNAMIC_IL
|
|
1071
|
-
CreateCompiledStaticFieldGetter(f)
|
|
1072
|
-
#else
|
|
1073
|
-
BuildStaticFieldGetterIL(f)
|
|
1074
|
-
#endif
|
|
1075
|
-
);
|
|
756
|
+
return DelegateFactory.GetStaticFieldGetter(field);
|
|
1076
757
|
}
|
|
1077
758
|
|
|
1078
759
|
#if EMIT_DYNAMIC_IL
|
|
@@ -1101,72 +782,11 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1101
782
|
/// </summary>
|
|
1102
783
|
public static Func<TInstance, TValue> GetFieldGetter<TInstance, TValue>(FieldInfo field)
|
|
1103
784
|
{
|
|
1104
|
-
|
|
1105
|
-
return Getter;
|
|
1106
|
-
TValue Getter(TInstance instance)
|
|
1107
|
-
{
|
|
1108
|
-
return (TValue)field.GetValue(instance);
|
|
1109
|
-
}
|
|
1110
|
-
#else
|
|
1111
|
-
DynamicMethod dynamicMethod = new(
|
|
1112
|
-
$"GetGeneric{field.DeclaringType.Name}_{field.Name}",
|
|
1113
|
-
typeof(TValue),
|
|
1114
|
-
new[] { typeof(TInstance) },
|
|
1115
|
-
field.DeclaringType,
|
|
1116
|
-
true
|
|
1117
|
-
);
|
|
1118
|
-
|
|
1119
|
-
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
1120
|
-
|
|
1121
|
-
if (!field.IsStatic)
|
|
1122
|
-
{
|
|
1123
|
-
if (typeof(TInstance).IsValueType)
|
|
1124
|
-
{
|
|
1125
|
-
il.Emit(OpCodes.Ldarga_S, 0);
|
|
1126
|
-
}
|
|
1127
|
-
else
|
|
1128
|
-
{
|
|
1129
|
-
il.Emit(OpCodes.Ldarg_0);
|
|
1130
|
-
}
|
|
1131
|
-
|
|
1132
|
-
if (field.DeclaringType != typeof(TInstance))
|
|
1133
|
-
{
|
|
1134
|
-
il.Emit(
|
|
1135
|
-
field.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
|
|
1136
|
-
field.DeclaringType
|
|
1137
|
-
);
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
il.Emit(OpCodes.Ldfld, field);
|
|
1141
|
-
}
|
|
1142
|
-
else
|
|
1143
|
-
{
|
|
1144
|
-
il.Emit(OpCodes.Ldsfld, field);
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
if (field.FieldType.IsValueType)
|
|
1148
|
-
{
|
|
1149
|
-
if (!typeof(TValue).IsValueType)
|
|
1150
|
-
{
|
|
1151
|
-
il.Emit(OpCodes.Box, field.FieldType);
|
|
1152
|
-
}
|
|
1153
|
-
}
|
|
1154
|
-
else
|
|
785
|
+
if (field == null)
|
|
1155
786
|
{
|
|
1156
|
-
|
|
1157
|
-
{
|
|
1158
|
-
il.Emit(OpCodes.Unbox_Any, typeof(TValue));
|
|
1159
|
-
}
|
|
1160
|
-
else if (typeof(TValue) != field.FieldType)
|
|
1161
|
-
{
|
|
1162
|
-
il.Emit(OpCodes.Castclass, typeof(TValue));
|
|
1163
|
-
}
|
|
787
|
+
throw new ArgumentNullException(nameof(field));
|
|
1164
788
|
}
|
|
1165
|
-
|
|
1166
|
-
il.Emit(OpCodes.Ret);
|
|
1167
|
-
return (Func<TInstance, TValue>)
|
|
1168
|
-
dynamicMethod.CreateDelegate(typeof(Func<TInstance, TValue>));
|
|
1169
|
-
#endif
|
|
789
|
+
return DelegateFactory.GetFieldGetterTyped<TInstance, TValue>(field);
|
|
1170
790
|
}
|
|
1171
791
|
|
|
1172
792
|
/// <summary>
|
|
@@ -1180,52 +800,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1180
800
|
/// <returns>Delegate: <c>() => TValue</c></returns>
|
|
1181
801
|
public static Func<TValue> GetStaticPropertyGetter<TValue>(PropertyInfo property)
|
|
1182
802
|
{
|
|
1183
|
-
|
|
1184
|
-
#if !EMIT_DYNAMIC_IL
|
|
1185
|
-
return Getter;
|
|
1186
|
-
TValue Getter()
|
|
1187
|
-
{
|
|
1188
|
-
// Use null for instance, null for indexer args for static properties
|
|
1189
|
-
return (TValue)property.GetValue(null, null);
|
|
1190
|
-
}
|
|
1191
|
-
#else
|
|
1192
|
-
DynamicMethod dynamicMethod = new(
|
|
1193
|
-
$"GetStatic_{property.DeclaringType.Name}_{property.Name}",
|
|
1194
|
-
typeof(TValue),
|
|
1195
|
-
Type.EmptyTypes,
|
|
1196
|
-
property.DeclaringType,
|
|
1197
|
-
true
|
|
1198
|
-
);
|
|
1199
|
-
|
|
1200
|
-
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
1201
|
-
|
|
1202
|
-
il.Emit(OpCodes.Call, getMethod);
|
|
1203
|
-
|
|
1204
|
-
Type actualType = property.PropertyType;
|
|
1205
|
-
Type targetType = typeof(TValue);
|
|
1206
|
-
|
|
1207
|
-
if (actualType != targetType)
|
|
1208
|
-
{
|
|
1209
|
-
if (actualType.IsValueType)
|
|
1210
|
-
{
|
|
1211
|
-
il.Emit(OpCodes.Box, actualType);
|
|
1212
|
-
if (targetType != typeof(object))
|
|
1213
|
-
{
|
|
1214
|
-
il.Emit(OpCodes.Castclass, targetType);
|
|
1215
|
-
}
|
|
1216
|
-
}
|
|
1217
|
-
else
|
|
1218
|
-
{
|
|
1219
|
-
il.Emit(
|
|
1220
|
-
targetType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass,
|
|
1221
|
-
targetType
|
|
1222
|
-
);
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
1225
|
-
|
|
1226
|
-
il.Emit(OpCodes.Ret);
|
|
1227
|
-
return (Func<TValue>)dynamicMethod.CreateDelegate(typeof(Func<TValue>));
|
|
1228
|
-
#endif
|
|
803
|
+
return DelegateFactory.GetStaticPropertyGetterTyped<TValue>(property);
|
|
1229
804
|
}
|
|
1230
805
|
|
|
1231
806
|
/// <summary>
|
|
@@ -1244,52 +819,8 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1244
819
|
{
|
|
1245
820
|
throw new ArgumentException(nameof(field));
|
|
1246
821
|
}
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
return Getter;
|
|
1250
|
-
TValue Getter()
|
|
1251
|
-
{
|
|
1252
|
-
return (TValue)field.GetValue(null);
|
|
1253
|
-
}
|
|
1254
|
-
#else
|
|
1255
|
-
DynamicMethod dynamicMethod = new(
|
|
1256
|
-
$"GetStatic_{field.DeclaringType.Name}_{field.Name}",
|
|
1257
|
-
typeof(TValue),
|
|
1258
|
-
Type.EmptyTypes,
|
|
1259
|
-
field.DeclaringType,
|
|
1260
|
-
true
|
|
1261
|
-
);
|
|
1262
|
-
|
|
1263
|
-
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
1264
|
-
|
|
1265
|
-
il.Emit(OpCodes.Ldsfld, field);
|
|
1266
|
-
|
|
1267
|
-
Type actualType = field.FieldType;
|
|
1268
|
-
Type targetType = typeof(TValue);
|
|
1269
|
-
|
|
1270
|
-
if (actualType != targetType)
|
|
1271
|
-
{
|
|
1272
|
-
if (actualType.IsValueType)
|
|
1273
|
-
{
|
|
1274
|
-
il.Emit(OpCodes.Box, actualType);
|
|
1275
|
-
if (targetType != typeof(object))
|
|
1276
|
-
{
|
|
1277
|
-
il.Emit(OpCodes.Castclass, targetType);
|
|
1278
|
-
}
|
|
1279
|
-
}
|
|
1280
|
-
else
|
|
1281
|
-
{
|
|
1282
|
-
il.Emit(
|
|
1283
|
-
targetType.IsValueType ? OpCodes.Unbox_Any : OpCodes.Castclass,
|
|
1284
|
-
targetType
|
|
1285
|
-
);
|
|
1286
|
-
}
|
|
1287
|
-
}
|
|
1288
|
-
|
|
1289
|
-
il.Emit(OpCodes.Ret);
|
|
1290
|
-
return (Func<TValue>)dynamicMethod.CreateDelegate(typeof(Func<TValue>));
|
|
1291
|
-
#endif
|
|
1292
|
-
}
|
|
822
|
+
return DelegateFactory.GetStaticFieldGetterTyped<TValue>(field);
|
|
823
|
+
}
|
|
1293
824
|
|
|
1294
825
|
/// <summary>
|
|
1295
826
|
/// Builds a strongly-typed field setter for instance fields.
|
|
@@ -1298,42 +829,11 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1298
829
|
FieldInfo field
|
|
1299
830
|
)
|
|
1300
831
|
{
|
|
1301
|
-
|
|
1302
|
-
return Setter;
|
|
1303
|
-
void Setter(ref TInstance instance, TValue newValue)
|
|
1304
|
-
{
|
|
1305
|
-
object value = instance;
|
|
1306
|
-
field.SetValue(value, newValue);
|
|
1307
|
-
instance = (TInstance)value;
|
|
1308
|
-
}
|
|
1309
|
-
#else
|
|
1310
|
-
Type instanceType = field.DeclaringType;
|
|
1311
|
-
Type valueType = field.FieldType;
|
|
1312
|
-
|
|
1313
|
-
DynamicMethod dynamicMethod = new(
|
|
1314
|
-
$"SetFieldGeneric{field.DeclaringType.Name}_{field.Name}",
|
|
1315
|
-
MethodAttributes.Public | MethodAttributes.Static,
|
|
1316
|
-
CallingConventions.Standard,
|
|
1317
|
-
typeof(void),
|
|
1318
|
-
new[] { instanceType.MakeByRefType(), valueType },
|
|
1319
|
-
field.Module,
|
|
1320
|
-
true
|
|
1321
|
-
);
|
|
1322
|
-
|
|
1323
|
-
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
1324
|
-
il.Emit(OpCodes.Ldarg_0);
|
|
1325
|
-
if (!instanceType.IsValueType)
|
|
832
|
+
if (field == null)
|
|
1326
833
|
{
|
|
1327
|
-
|
|
834
|
+
throw new ArgumentNullException(nameof(field));
|
|
1328
835
|
}
|
|
1329
|
-
|
|
1330
|
-
il.Emit(OpCodes.Ldarg_1);
|
|
1331
|
-
il.Emit(OpCodes.Stfld, field);
|
|
1332
|
-
il.Emit(OpCodes.Ret);
|
|
1333
|
-
|
|
1334
|
-
Type delegateType = typeof(FieldSetter<,>).MakeGenericType(instanceType, valueType);
|
|
1335
|
-
return (FieldSetter<TInstance, TValue>)dynamicMethod.CreateDelegate(delegateType);
|
|
1336
|
-
#endif
|
|
836
|
+
return DelegateFactory.GetFieldSetterTyped<TInstance, TValue>(field);
|
|
1337
837
|
}
|
|
1338
838
|
|
|
1339
839
|
/// <summary>
|
|
@@ -1352,28 +852,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1352
852
|
{
|
|
1353
853
|
throw new ArgumentException(nameof(field));
|
|
1354
854
|
}
|
|
1355
|
-
|
|
1356
|
-
return Setter;
|
|
1357
|
-
void Setter(TValue newValue)
|
|
1358
|
-
{
|
|
1359
|
-
field.SetValue(null, newValue);
|
|
1360
|
-
}
|
|
1361
|
-
#else
|
|
1362
|
-
DynamicMethod dynamicMethod = new(
|
|
1363
|
-
$"SetFieldGenericStatic{field.DeclaringType.Name}_{field.Name}",
|
|
1364
|
-
typeof(void),
|
|
1365
|
-
new[] { typeof(TValue) },
|
|
1366
|
-
field.Module,
|
|
1367
|
-
true
|
|
1368
|
-
);
|
|
1369
|
-
|
|
1370
|
-
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
1371
|
-
il.Emit(OpCodes.Ldarg_0);
|
|
1372
|
-
il.Emit(OpCodes.Stsfld, field);
|
|
1373
|
-
il.Emit(OpCodes.Ret);
|
|
1374
|
-
|
|
1375
|
-
return (Action<TValue>)dynamicMethod.CreateDelegate(typeof(Action<TValue>));
|
|
1376
|
-
#endif
|
|
855
|
+
return DelegateFactory.GetStaticFieldSetterTyped<TValue>(field);
|
|
1377
856
|
}
|
|
1378
857
|
|
|
1379
858
|
/// <summary>
|
|
@@ -1387,13 +866,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1387
866
|
/// <returns>Delegate: <c>(object instance, object value) => void</c></returns>
|
|
1388
867
|
public static Action<object, object> GetFieldSetter(FieldInfo field)
|
|
1389
868
|
{
|
|
1390
|
-
return
|
|
1391
|
-
#if !EMIT_DYNAMIC_IL
|
|
1392
|
-
CreateCompiledFieldSetter(f)
|
|
1393
|
-
#else
|
|
1394
|
-
BuildFieldSetterIL(f)
|
|
1395
|
-
#endif
|
|
1396
|
-
);
|
|
869
|
+
return DelegateFactory.GetFieldSetter(field);
|
|
1397
870
|
}
|
|
1398
871
|
|
|
1399
872
|
#if EMIT_DYNAMIC_IL
|
|
@@ -1439,13 +912,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1439
912
|
{
|
|
1440
913
|
throw new ArgumentException(nameof(field));
|
|
1441
914
|
}
|
|
1442
|
-
return
|
|
1443
|
-
#if !EMIT_DYNAMIC_IL
|
|
1444
|
-
CreateCompiledStaticFieldSetter(f)
|
|
1445
|
-
#else
|
|
1446
|
-
BuildStaticFieldSetterIL(f)
|
|
1447
|
-
#endif
|
|
1448
|
-
);
|
|
915
|
+
return DelegateFactory.GetStaticFieldSetter(field);
|
|
1449
916
|
}
|
|
1450
917
|
|
|
1451
918
|
#if EMIT_DYNAMIC_IL
|
|
@@ -1579,7 +1046,6 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1579
1046
|
#endif
|
|
1580
1047
|
}
|
|
1581
1048
|
|
|
1582
|
-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
1583
1049
|
/// <summary>
|
|
1584
1050
|
/// Creates a <see cref="HashSet{T}"/> instance for the given element type with capacity.
|
|
1585
1051
|
/// </summary>
|
|
@@ -1591,12 +1057,10 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1591
1057
|
/// object set = ReflectionHelpers.CreateHashSet(typeof(string), 64); // HashSet<string>
|
|
1592
1058
|
/// ]]></code>
|
|
1593
1059
|
/// </example>
|
|
1060
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
1594
1061
|
public static object CreateHashSet(Type elementType, int capacity)
|
|
1595
1062
|
{
|
|
1596
|
-
return
|
|
1597
|
-
// ReSharper disable once ConvertClosureToMethodGroup
|
|
1598
|
-
.GetOrAdd(elementType, type => GetHashSetWithCapacityCreator(type))
|
|
1599
|
-
.Invoke(capacity);
|
|
1063
|
+
return GetHashSetWithCapacityCreatorCached(elementType).Invoke(capacity);
|
|
1600
1064
|
}
|
|
1601
1065
|
|
|
1602
1066
|
/// <summary>
|
|
@@ -1724,6 +1188,48 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1724
1188
|
#endif
|
|
1725
1189
|
}
|
|
1726
1190
|
|
|
1191
|
+
public static Action<object> GetHashSetClearer(Type elementType)
|
|
1192
|
+
{
|
|
1193
|
+
if (elementType == null)
|
|
1194
|
+
{
|
|
1195
|
+
throw new ArgumentNullException(nameof(elementType));
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
return HashSetClearers.GetOrAdd(
|
|
1199
|
+
elementType,
|
|
1200
|
+
static type =>
|
|
1201
|
+
{
|
|
1202
|
+
Type hashSetType = typeof(HashSet<>).MakeGenericType(type);
|
|
1203
|
+
MethodInfo clearMethod = hashSetType.GetMethod("Clear", Type.EmptyTypes);
|
|
1204
|
+
if (clearMethod == null)
|
|
1205
|
+
{
|
|
1206
|
+
return _ => { };
|
|
1207
|
+
}
|
|
1208
|
+
#if SUPPORT_EXPRESSION_COMPILE
|
|
1209
|
+
if (ExpressionsEnabled)
|
|
1210
|
+
{
|
|
1211
|
+
try
|
|
1212
|
+
{
|
|
1213
|
+
ParameterExpression target = Expression.Parameter(
|
|
1214
|
+
typeof(object),
|
|
1215
|
+
"set"
|
|
1216
|
+
);
|
|
1217
|
+
UnaryExpression cast = Expression.Convert(target, hashSetType);
|
|
1218
|
+
MethodCallExpression call = Expression.Call(cast, clearMethod);
|
|
1219
|
+
return Expression.Lambda<Action<object>>(call, target).Compile();
|
|
1220
|
+
}
|
|
1221
|
+
catch
|
|
1222
|
+
{
|
|
1223
|
+
// Fall through to reflection fallback
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
#endif
|
|
1227
|
+
MethodInfo closedMethod = clearMethod;
|
|
1228
|
+
return set => closedMethod.Invoke(set, Array.Empty<object>());
|
|
1229
|
+
}
|
|
1230
|
+
);
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1727
1233
|
/// <summary>
|
|
1728
1234
|
/// Invokes an instance method using a cached invoker; avoids per-call reflection overhead.
|
|
1729
1235
|
/// </summary>
|
|
@@ -1732,22 +1238,13 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1732
1238
|
/// <param name="parameters">Optional parameters.</param>
|
|
1733
1239
|
/// <returns>The return value from the method, or null for void.</returns>
|
|
1734
1240
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
1735
|
-
/// <summary>
|
|
1736
|
-
/// Invokes an instance method using a cached delegate when possible.
|
|
1737
|
-
/// </summary>
|
|
1738
|
-
/// <param name="method">Instance method to invoke.</param>
|
|
1739
|
-
/// <param name="instance">Target instance.</param>
|
|
1740
|
-
/// <param name="parameters">Method parameters (optional).</param>
|
|
1741
|
-
/// <returns>Boxed return value or null for void methods.</returns>
|
|
1742
1241
|
public static object InvokeMethod(
|
|
1743
1242
|
MethodInfo method,
|
|
1744
1243
|
object instance,
|
|
1745
1244
|
params object[] parameters
|
|
1746
1245
|
)
|
|
1747
1246
|
{
|
|
1748
|
-
return
|
|
1749
|
-
.GetOrAdd(method, methodInfo => GetMethodInvoker(methodInfo))
|
|
1750
|
-
.Invoke(instance, parameters);
|
|
1247
|
+
return DelegateFactory.GetMethodInvoker(method).Invoke(instance, parameters);
|
|
1751
1248
|
}
|
|
1752
1249
|
|
|
1753
1250
|
/// <summary>
|
|
@@ -1757,40 +1254,23 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1757
1254
|
/// <param name="parameters">Optional parameters.</param>
|
|
1758
1255
|
/// <returns>The return value from the method, or null for void.</returns>
|
|
1759
1256
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
1760
|
-
/// <summary>
|
|
1761
|
-
/// Invokes a static method using a cached delegate when possible.
|
|
1762
|
-
/// </summary>
|
|
1763
|
-
/// <param name="method">Static method.</param>
|
|
1764
|
-
/// <param name="parameters">Method parameters.</param>
|
|
1765
|
-
/// <returns>Boxed return value or null for void methods.</returns>
|
|
1766
1257
|
public static object InvokeStaticMethod(MethodInfo method, params object[] parameters)
|
|
1767
1258
|
{
|
|
1768
|
-
return
|
|
1769
|
-
.GetOrAdd(method, methodInfo => GetStaticMethodInvoker(methodInfo))
|
|
1770
|
-
.Invoke(parameters);
|
|
1259
|
+
return DelegateFactory.GetStaticMethodInvoker(method).Invoke(parameters);
|
|
1771
1260
|
}
|
|
1772
1261
|
|
|
1773
|
-
/// <summary>
|
|
1774
|
-
/// Constructs an instance using a cached constructor invoker.
|
|
1775
|
-
/// </summary>
|
|
1776
|
-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
1777
1262
|
/// <summary>
|
|
1778
1263
|
/// Creates an instance using a constructor via a cached delegate.
|
|
1779
1264
|
/// </summary>
|
|
1780
1265
|
/// <param name="constructor">Constructor to invoke.</param>
|
|
1781
1266
|
/// <param name="parameters">Constructor parameters.</param>
|
|
1782
1267
|
/// <returns>Created instance.</returns>
|
|
1268
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
1783
1269
|
public static object CreateInstance(ConstructorInfo constructor, params object[] parameters)
|
|
1784
1270
|
{
|
|
1785
|
-
return
|
|
1786
|
-
.GetOrAdd(constructor, ctor => GetConstructor(ctor))
|
|
1787
|
-
.Invoke(parameters);
|
|
1271
|
+
return DelegateFactory.GetConstructorInvoker(constructor).Invoke(parameters);
|
|
1788
1272
|
}
|
|
1789
1273
|
|
|
1790
|
-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
1791
|
-
/// <summary>
|
|
1792
|
-
/// Constructs an instance using a cached constructor invoker and returns it as T.
|
|
1793
|
-
/// </summary>
|
|
1794
1274
|
/// <summary>
|
|
1795
1275
|
/// Constructs an instance using a cached constructor invoker and returns it as T.
|
|
1796
1276
|
/// </summary>
|
|
@@ -1805,6 +1285,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1805
1285
|
/// var p = ReflectionHelpers.CreateInstance<Player>(name, level);
|
|
1806
1286
|
/// ]]></code>
|
|
1807
1287
|
/// </example>
|
|
1288
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
1808
1289
|
public static T CreateInstance<T>(params object[] parameters)
|
|
1809
1290
|
{
|
|
1810
1291
|
Type type = typeof(T);
|
|
@@ -1853,60 +1334,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1853
1334
|
nameof(method)
|
|
1854
1335
|
);
|
|
1855
1336
|
}
|
|
1856
|
-
|
|
1857
|
-
#if !EMIT_DYNAMIC_IL
|
|
1858
|
-
return CreateCompiledMethodInvoker(method);
|
|
1859
|
-
#else
|
|
1860
|
-
DynamicMethod dynamicMethod = new(
|
|
1861
|
-
$"Invoke{method.DeclaringType.Name}_{method.Name}",
|
|
1862
|
-
typeof(object),
|
|
1863
|
-
new[] { typeof(object), typeof(object[]) },
|
|
1864
|
-
method.DeclaringType,
|
|
1865
|
-
true
|
|
1866
|
-
);
|
|
1867
|
-
|
|
1868
|
-
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
1869
|
-
ParameterInfo[] parameters = method.GetParameters();
|
|
1870
|
-
|
|
1871
|
-
il.Emit(OpCodes.Ldarg_0);
|
|
1872
|
-
il.Emit(
|
|
1873
|
-
method.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
|
|
1874
|
-
method.DeclaringType
|
|
1875
|
-
);
|
|
1876
|
-
|
|
1877
|
-
for (int i = 0; i < parameters.Length; i++)
|
|
1878
|
-
{
|
|
1879
|
-
il.Emit(OpCodes.Ldarg_1);
|
|
1880
|
-
il.Emit(OpCodes.Ldc_I4, i);
|
|
1881
|
-
il.Emit(OpCodes.Ldelem_Ref);
|
|
1882
|
-
|
|
1883
|
-
Type paramType = parameters[i].ParameterType;
|
|
1884
|
-
if (paramType.IsValueType)
|
|
1885
|
-
{
|
|
1886
|
-
il.Emit(OpCodes.Unbox_Any, paramType);
|
|
1887
|
-
}
|
|
1888
|
-
else
|
|
1889
|
-
{
|
|
1890
|
-
il.Emit(OpCodes.Castclass, paramType);
|
|
1891
|
-
}
|
|
1892
|
-
}
|
|
1893
|
-
|
|
1894
|
-
il.Emit(method.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt, method);
|
|
1895
|
-
|
|
1896
|
-
if (method.ReturnType == typeof(void))
|
|
1897
|
-
{
|
|
1898
|
-
il.Emit(OpCodes.Ldnull);
|
|
1899
|
-
}
|
|
1900
|
-
else if (method.ReturnType.IsValueType)
|
|
1901
|
-
{
|
|
1902
|
-
il.Emit(OpCodes.Box, method.ReturnType);
|
|
1903
|
-
}
|
|
1904
|
-
|
|
1905
|
-
il.Emit(OpCodes.Ret);
|
|
1906
|
-
|
|
1907
|
-
return (Func<object, object[], object>)
|
|
1908
|
-
dynamicMethod.CreateDelegate(typeof(Func<object, object[], object>));
|
|
1909
|
-
#endif
|
|
1337
|
+
return DelegateFactory.GetMethodInvoker(method);
|
|
1910
1338
|
}
|
|
1911
1339
|
|
|
1912
1340
|
/// <summary>
|
|
@@ -1918,54 +1346,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1918
1346
|
{
|
|
1919
1347
|
throw new ArgumentException("Method must be static", nameof(method));
|
|
1920
1348
|
}
|
|
1921
|
-
|
|
1922
|
-
#if !EMIT_DYNAMIC_IL
|
|
1923
|
-
return CreateCompiledStaticMethodInvoker(method);
|
|
1924
|
-
#else
|
|
1925
|
-
DynamicMethod dynamicMethod = new(
|
|
1926
|
-
$"InvokeStatic{method.DeclaringType.Name}_{method.Name}",
|
|
1927
|
-
typeof(object),
|
|
1928
|
-
new[] { typeof(object[]) },
|
|
1929
|
-
method.DeclaringType,
|
|
1930
|
-
true
|
|
1931
|
-
);
|
|
1932
|
-
|
|
1933
|
-
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
1934
|
-
ParameterInfo[] parameters = method.GetParameters();
|
|
1935
|
-
|
|
1936
|
-
for (int i = 0; i < parameters.Length; i++)
|
|
1937
|
-
{
|
|
1938
|
-
il.Emit(OpCodes.Ldarg_0);
|
|
1939
|
-
il.Emit(OpCodes.Ldc_I4, i);
|
|
1940
|
-
il.Emit(OpCodes.Ldelem_Ref);
|
|
1941
|
-
|
|
1942
|
-
Type paramType = parameters[i].ParameterType;
|
|
1943
|
-
if (paramType.IsValueType)
|
|
1944
|
-
{
|
|
1945
|
-
il.Emit(OpCodes.Unbox_Any, paramType);
|
|
1946
|
-
}
|
|
1947
|
-
else
|
|
1948
|
-
{
|
|
1949
|
-
il.Emit(OpCodes.Castclass, paramType);
|
|
1950
|
-
}
|
|
1951
|
-
}
|
|
1952
|
-
|
|
1953
|
-
il.Emit(OpCodes.Call, method);
|
|
1954
|
-
|
|
1955
|
-
if (method.ReturnType == typeof(void))
|
|
1956
|
-
{
|
|
1957
|
-
il.Emit(OpCodes.Ldnull);
|
|
1958
|
-
}
|
|
1959
|
-
else if (method.ReturnType.IsValueType)
|
|
1960
|
-
{
|
|
1961
|
-
il.Emit(OpCodes.Box, method.ReturnType);
|
|
1962
|
-
}
|
|
1963
|
-
|
|
1964
|
-
il.Emit(OpCodes.Ret);
|
|
1965
|
-
|
|
1966
|
-
return (Func<object[], object>)
|
|
1967
|
-
dynamicMethod.CreateDelegate(typeof(Func<object[], object>));
|
|
1968
|
-
#endif
|
|
1349
|
+
return DelegateFactory.GetStaticMethodInvoker(method);
|
|
1969
1350
|
}
|
|
1970
1351
|
|
|
1971
1352
|
/// <summary>
|
|
@@ -1973,49 +1354,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
1973
1354
|
/// </summary>
|
|
1974
1355
|
public static Func<object[], object> GetConstructor(ConstructorInfo constructor)
|
|
1975
1356
|
{
|
|
1976
|
-
|
|
1977
|
-
return CreateCompiledConstructor(constructor);
|
|
1978
|
-
#else
|
|
1979
|
-
DynamicMethod dynamicMethod = new(
|
|
1980
|
-
$"Create{constructor.DeclaringType.Name}",
|
|
1981
|
-
typeof(object),
|
|
1982
|
-
new[] { typeof(object[]) },
|
|
1983
|
-
constructor.DeclaringType,
|
|
1984
|
-
true
|
|
1985
|
-
);
|
|
1986
|
-
|
|
1987
|
-
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
1988
|
-
ParameterInfo[] parameters = constructor.GetParameters();
|
|
1989
|
-
|
|
1990
|
-
for (int i = 0; i < parameters.Length; i++)
|
|
1991
|
-
{
|
|
1992
|
-
il.Emit(OpCodes.Ldarg_0);
|
|
1993
|
-
il.Emit(OpCodes.Ldc_I4, i);
|
|
1994
|
-
il.Emit(OpCodes.Ldelem_Ref);
|
|
1995
|
-
|
|
1996
|
-
Type paramType = parameters[i].ParameterType;
|
|
1997
|
-
if (paramType.IsValueType)
|
|
1998
|
-
{
|
|
1999
|
-
il.Emit(OpCodes.Unbox_Any, paramType);
|
|
2000
|
-
}
|
|
2001
|
-
else
|
|
2002
|
-
{
|
|
2003
|
-
il.Emit(OpCodes.Castclass, paramType);
|
|
2004
|
-
}
|
|
2005
|
-
}
|
|
2006
|
-
|
|
2007
|
-
il.Emit(OpCodes.Newobj, constructor);
|
|
2008
|
-
|
|
2009
|
-
if (constructor.DeclaringType.IsValueType)
|
|
2010
|
-
{
|
|
2011
|
-
il.Emit(OpCodes.Box, constructor.DeclaringType);
|
|
2012
|
-
}
|
|
2013
|
-
|
|
2014
|
-
il.Emit(OpCodes.Ret);
|
|
2015
|
-
|
|
2016
|
-
return (Func<object[], object>)
|
|
2017
|
-
dynamicMethod.CreateDelegate(typeof(Func<object[], object>));
|
|
2018
|
-
#endif
|
|
1357
|
+
return DelegateFactory.GetConstructorInvoker(constructor);
|
|
2019
1358
|
}
|
|
2020
1359
|
|
|
2021
1360
|
/// <summary>
|
|
@@ -2050,20 +1389,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
2050
1389
|
throw new ArgumentException("Method signature does not match <T1,T2,TReturn>.");
|
|
2051
1390
|
}
|
|
2052
1391
|
|
|
2053
|
-
|
|
2054
|
-
if (!TypedStaticInvoker2.TryGetValue(method, out Delegate del))
|
|
2055
|
-
{
|
|
2056
|
-
del = BuildTypedStaticInvoker2<T1, T2, TReturn>(method);
|
|
2057
|
-
TypedStaticInvoker2[method] = del;
|
|
2058
|
-
}
|
|
2059
|
-
return (Func<T1, T2, TReturn>)del;
|
|
2060
|
-
#else
|
|
2061
|
-
Delegate del = TypedStaticInvoker2.GetOrAdd(
|
|
2062
|
-
method,
|
|
2063
|
-
m => BuildTypedStaticInvoker2<T1, T2, TReturn>(m)
|
|
2064
|
-
);
|
|
2065
|
-
return (Func<T1, T2, TReturn>)del;
|
|
2066
|
-
#endif
|
|
1392
|
+
return DelegateFactory.GetStaticMethodInvokerTyped<T1, T2, TReturn>(method);
|
|
2067
1393
|
}
|
|
2068
1394
|
|
|
2069
1395
|
public static Func<int, T[]> GetArrayCreator<T>()
|
|
@@ -2178,20 +1504,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
2178
1504
|
{
|
|
2179
1505
|
throw new ArgumentException("Method signature does not match <TReturn>.");
|
|
2180
1506
|
}
|
|
2181
|
-
|
|
2182
|
-
if (!TypedStaticInvoker0.TryGetValue(method, out Delegate del))
|
|
2183
|
-
{
|
|
2184
|
-
del = BuildTypedStaticInvoker0<TReturn>(method);
|
|
2185
|
-
TypedStaticInvoker0[method] = del;
|
|
2186
|
-
}
|
|
2187
|
-
return (Func<TReturn>)del;
|
|
2188
|
-
#else
|
|
2189
|
-
Delegate del = TypedStaticInvoker0.GetOrAdd(
|
|
2190
|
-
method,
|
|
2191
|
-
m => BuildTypedStaticInvoker0<TReturn>(m)
|
|
2192
|
-
);
|
|
2193
|
-
return (Func<TReturn>)del;
|
|
2194
|
-
#endif
|
|
1507
|
+
return DelegateFactory.GetStaticMethodInvokerTyped<TReturn>(method);
|
|
2195
1508
|
}
|
|
2196
1509
|
|
|
2197
1510
|
public static Func<T1, TReturn> GetStaticMethodInvoker<T1, TReturn>(MethodInfo method)
|
|
@@ -2215,20 +1528,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
2215
1528
|
"ref/out parameters are not supported in typed invokers"
|
|
2216
1529
|
);
|
|
2217
1530
|
}
|
|
2218
|
-
|
|
2219
|
-
if (!TypedStaticInvoker1.TryGetValue(method, out Delegate del))
|
|
2220
|
-
{
|
|
2221
|
-
del = BuildTypedStaticInvoker1<T1, TReturn>(method);
|
|
2222
|
-
TypedStaticInvoker1[method] = del;
|
|
2223
|
-
}
|
|
2224
|
-
return (Func<T1, TReturn>)del;
|
|
2225
|
-
#else
|
|
2226
|
-
Delegate del = TypedStaticInvoker1.GetOrAdd(
|
|
2227
|
-
method,
|
|
2228
|
-
m => BuildTypedStaticInvoker1<T1, TReturn>(m)
|
|
2229
|
-
);
|
|
2230
|
-
return (Func<T1, TReturn>)del;
|
|
2231
|
-
#endif
|
|
1531
|
+
return DelegateFactory.GetStaticMethodInvokerTyped<T1, TReturn>(method);
|
|
2232
1532
|
}
|
|
2233
1533
|
|
|
2234
1534
|
public static Func<T1, T2, T3, TReturn> GetStaticMethodInvoker<T1, T2, T3, TReturn>(
|
|
@@ -2259,20 +1559,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
2259
1559
|
"ref/out parameters are not supported in typed invokers"
|
|
2260
1560
|
);
|
|
2261
1561
|
}
|
|
2262
|
-
|
|
2263
|
-
if (!TypedStaticInvoker3.TryGetValue(method, out Delegate del))
|
|
2264
|
-
{
|
|
2265
|
-
del = BuildTypedStaticInvoker3<T1, T2, T3, TReturn>(method);
|
|
2266
|
-
TypedStaticInvoker3[method] = del;
|
|
2267
|
-
}
|
|
2268
|
-
return (Func<T1, T2, T3, TReturn>)del;
|
|
2269
|
-
#else
|
|
2270
|
-
Delegate del = TypedStaticInvoker3.GetOrAdd(
|
|
2271
|
-
method,
|
|
2272
|
-
m => BuildTypedStaticInvoker3<T1, T2, T3, TReturn>(m)
|
|
2273
|
-
);
|
|
2274
|
-
return (Func<T1, T2, T3, TReturn>)del;
|
|
2275
|
-
#endif
|
|
1562
|
+
return DelegateFactory.GetStaticMethodInvokerTyped<T1, T2, T3, TReturn>(method);
|
|
2276
1563
|
}
|
|
2277
1564
|
|
|
2278
1565
|
public static Func<T1, T2, T3, T4, TReturn> GetStaticMethodInvoker<T1, T2, T3, T4, TReturn>(
|
|
@@ -2306,93 +1593,31 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
2306
1593
|
"ref/out parameters are not supported in typed invokers"
|
|
2307
1594
|
);
|
|
2308
1595
|
}
|
|
2309
|
-
|
|
2310
|
-
if (!TypedStaticInvoker4.TryGetValue(method, out Delegate del))
|
|
2311
|
-
{
|
|
2312
|
-
del = BuildTypedStaticInvoker4<T1, T2, T3, T4, TReturn>(method);
|
|
2313
|
-
TypedStaticInvoker4[method] = del;
|
|
2314
|
-
}
|
|
2315
|
-
return (Func<T1, T2, T3, T4, TReturn>)del;
|
|
2316
|
-
#else
|
|
2317
|
-
Delegate del = TypedStaticInvoker4.GetOrAdd(
|
|
2318
|
-
method,
|
|
2319
|
-
m => BuildTypedStaticInvoker4<T1, T2, T3, T4, TReturn>(m)
|
|
2320
|
-
);
|
|
2321
|
-
return (Func<T1, T2, T3, T4, TReturn>)del;
|
|
2322
|
-
#endif
|
|
1596
|
+
return DelegateFactory.GetStaticMethodInvokerTyped<T1, T2, T3, T4, TReturn>(method);
|
|
2323
1597
|
}
|
|
2324
1598
|
|
|
2325
1599
|
public static Action GetStaticActionInvoker(MethodInfo method)
|
|
2326
1600
|
{
|
|
2327
1601
|
ValidateStaticActionSignature(method);
|
|
2328
|
-
|
|
2329
|
-
if (!TypedStaticAction0.TryGetValue(method, out Delegate del))
|
|
2330
|
-
{
|
|
2331
|
-
del = BuildStaticActionInvoker0(method);
|
|
2332
|
-
TypedStaticAction0[method] = del;
|
|
2333
|
-
}
|
|
2334
|
-
return (Action)del;
|
|
2335
|
-
#else
|
|
2336
|
-
Delegate del = TypedStaticAction0.GetOrAdd(method, m => BuildStaticActionInvoker0(m));
|
|
2337
|
-
return (Action)del;
|
|
2338
|
-
#endif
|
|
1602
|
+
return DelegateFactory.GetStaticActionInvokerTyped(method);
|
|
2339
1603
|
}
|
|
2340
1604
|
|
|
2341
1605
|
public static Action<T1> GetStaticActionInvoker<T1>(MethodInfo method)
|
|
2342
1606
|
{
|
|
2343
1607
|
ValidateStaticActionSignature(method, typeof(T1));
|
|
2344
|
-
|
|
2345
|
-
if (!TypedStaticAction1.TryGetValue(method, out Delegate del))
|
|
2346
|
-
{
|
|
2347
|
-
del = BuildStaticActionInvoker1<T1>(method);
|
|
2348
|
-
TypedStaticAction1[method] = del;
|
|
2349
|
-
}
|
|
2350
|
-
return (Action<T1>)del;
|
|
2351
|
-
#else
|
|
2352
|
-
Delegate del = TypedStaticAction1.GetOrAdd(
|
|
2353
|
-
method,
|
|
2354
|
-
m => BuildStaticActionInvoker1<T1>(m)
|
|
2355
|
-
);
|
|
2356
|
-
return (Action<T1>)del;
|
|
2357
|
-
#endif
|
|
1608
|
+
return DelegateFactory.GetStaticActionInvokerTyped<T1>(method);
|
|
2358
1609
|
}
|
|
2359
1610
|
|
|
2360
1611
|
public static Action<T1, T2> GetStaticActionInvoker<T1, T2>(MethodInfo method)
|
|
2361
1612
|
{
|
|
2362
1613
|
ValidateStaticActionSignature(method, typeof(T1), typeof(T2));
|
|
2363
|
-
|
|
2364
|
-
if (!TypedStaticAction2.TryGetValue(method, out Delegate del))
|
|
2365
|
-
{
|
|
2366
|
-
del = BuildStaticActionInvoker2<T1, T2>(method);
|
|
2367
|
-
TypedStaticAction2[method] = del;
|
|
2368
|
-
}
|
|
2369
|
-
return (Action<T1, T2>)del;
|
|
2370
|
-
#else
|
|
2371
|
-
Delegate del = TypedStaticAction2.GetOrAdd(
|
|
2372
|
-
method,
|
|
2373
|
-
m => BuildStaticActionInvoker2<T1, T2>(m)
|
|
2374
|
-
);
|
|
2375
|
-
return (Action<T1, T2>)del;
|
|
2376
|
-
#endif
|
|
1614
|
+
return DelegateFactory.GetStaticActionInvokerTyped<T1, T2>(method);
|
|
2377
1615
|
}
|
|
2378
1616
|
|
|
2379
1617
|
public static Action<T1, T2, T3> GetStaticActionInvoker<T1, T2, T3>(MethodInfo method)
|
|
2380
1618
|
{
|
|
2381
1619
|
ValidateStaticActionSignature(method, typeof(T1), typeof(T2), typeof(T3));
|
|
2382
|
-
|
|
2383
|
-
if (!TypedStaticAction3.TryGetValue(method, out Delegate del))
|
|
2384
|
-
{
|
|
2385
|
-
del = BuildStaticActionInvoker3<T1, T2, T3>(method);
|
|
2386
|
-
TypedStaticAction3[method] = del;
|
|
2387
|
-
}
|
|
2388
|
-
return (Action<T1, T2, T3>)del;
|
|
2389
|
-
#else
|
|
2390
|
-
Delegate del = TypedStaticAction3.GetOrAdd(
|
|
2391
|
-
method,
|
|
2392
|
-
m => BuildStaticActionInvoker3<T1, T2, T3>(m)
|
|
2393
|
-
);
|
|
2394
|
-
return (Action<T1, T2, T3>)del;
|
|
2395
|
-
#endif
|
|
1620
|
+
return DelegateFactory.GetStaticActionInvokerTyped<T1, T2, T3>(method);
|
|
2396
1621
|
}
|
|
2397
1622
|
|
|
2398
1623
|
public static Action<T1, T2, T3, T4> GetStaticActionInvoker<T1, T2, T3, T4>(
|
|
@@ -2400,20 +1625,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
2400
1625
|
)
|
|
2401
1626
|
{
|
|
2402
1627
|
ValidateStaticActionSignature(method, typeof(T1), typeof(T2), typeof(T3), typeof(T4));
|
|
2403
|
-
|
|
2404
|
-
if (!TypedStaticAction4.TryGetValue(method, out Delegate del))
|
|
2405
|
-
{
|
|
2406
|
-
del = BuildStaticActionInvoker4<T1, T2, T3, T4>(method);
|
|
2407
|
-
TypedStaticAction4[method] = del;
|
|
2408
|
-
}
|
|
2409
|
-
return (Action<T1, T2, T3, T4>)del;
|
|
2410
|
-
#else
|
|
2411
|
-
Delegate del = TypedStaticAction4.GetOrAdd(
|
|
2412
|
-
method,
|
|
2413
|
-
m => BuildStaticActionInvoker4<T1, T2, T3, T4>(m)
|
|
2414
|
-
);
|
|
2415
|
-
return (Action<T1, T2, T3, T4>)del;
|
|
2416
|
-
#endif
|
|
1628
|
+
return DelegateFactory.GetStaticActionInvokerTyped<T1, T2, T3, T4>(method);
|
|
2417
1629
|
}
|
|
2418
1630
|
|
|
2419
1631
|
public static Func<TInstance, TReturn> GetInstanceMethodInvoker<TInstance, TReturn>(
|
|
@@ -2421,20 +1633,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
2421
1633
|
)
|
|
2422
1634
|
{
|
|
2423
1635
|
ValidateInstanceFuncSignature<TInstance, TReturn>(method, Type.EmptyTypes);
|
|
2424
|
-
|
|
2425
|
-
if (!TypedInstanceInvoker0.TryGetValue(method, out Delegate del))
|
|
2426
|
-
{
|
|
2427
|
-
del = BuildInstanceInvoker0<TInstance, TReturn>(method);
|
|
2428
|
-
TypedInstanceInvoker0[method] = del;
|
|
2429
|
-
}
|
|
2430
|
-
return (Func<TInstance, TReturn>)del;
|
|
2431
|
-
#else
|
|
2432
|
-
Delegate del = TypedInstanceInvoker0.GetOrAdd(
|
|
2433
|
-
method,
|
|
2434
|
-
m => BuildInstanceInvoker0<TInstance, TReturn>(m)
|
|
2435
|
-
);
|
|
2436
|
-
return (Func<TInstance, TReturn>)del;
|
|
2437
|
-
#endif
|
|
1636
|
+
return DelegateFactory.GetInstanceMethodInvokerTyped<TInstance, TReturn>(method);
|
|
2438
1637
|
}
|
|
2439
1638
|
|
|
2440
1639
|
public static Func<TInstance, T1, TReturn> GetInstanceMethodInvoker<TInstance, T1, TReturn>(
|
|
@@ -2442,20 +1641,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
2442
1641
|
)
|
|
2443
1642
|
{
|
|
2444
1643
|
ValidateInstanceFuncSignature<TInstance, TReturn>(method, new[] { typeof(T1) });
|
|
2445
|
-
|
|
2446
|
-
if (!TypedInstanceInvoker1.TryGetValue(method, out Delegate del))
|
|
2447
|
-
{
|
|
2448
|
-
del = BuildInstanceInvoker1<TInstance, T1, TReturn>(method);
|
|
2449
|
-
TypedInstanceInvoker1[method] = del;
|
|
2450
|
-
}
|
|
2451
|
-
return (Func<TInstance, T1, TReturn>)del;
|
|
2452
|
-
#else
|
|
2453
|
-
Delegate del = TypedInstanceInvoker1.GetOrAdd(
|
|
2454
|
-
method,
|
|
2455
|
-
m => BuildInstanceInvoker1<TInstance, T1, TReturn>(m)
|
|
2456
|
-
);
|
|
2457
|
-
return (Func<TInstance, T1, TReturn>)del;
|
|
2458
|
-
#endif
|
|
1644
|
+
return DelegateFactory.GetInstanceMethodInvokerTyped<TInstance, T1, TReturn>(method);
|
|
2459
1645
|
}
|
|
2460
1646
|
|
|
2461
1647
|
public static Func<TInstance, T1, T2, TReturn> GetInstanceMethodInvoker<
|
|
@@ -2469,20 +1655,9 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
2469
1655
|
method,
|
|
2470
1656
|
new[] { typeof(T1), typeof(T2) }
|
|
2471
1657
|
);
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
{
|
|
2475
|
-
del = BuildInstanceInvoker2<TInstance, T1, T2, TReturn>(method);
|
|
2476
|
-
TypedInstanceInvoker2[method] = del;
|
|
2477
|
-
}
|
|
2478
|
-
return (Func<TInstance, T1, T2, TReturn>)del;
|
|
2479
|
-
#else
|
|
2480
|
-
Delegate del = TypedInstanceInvoker2.GetOrAdd(
|
|
2481
|
-
method,
|
|
2482
|
-
m => BuildInstanceInvoker2<TInstance, T1, T2, TReturn>(m)
|
|
1658
|
+
return DelegateFactory.GetInstanceMethodInvokerTyped<TInstance, T1, T2, TReturn>(
|
|
1659
|
+
method
|
|
2483
1660
|
);
|
|
2484
|
-
return (Func<TInstance, T1, T2, TReturn>)del;
|
|
2485
|
-
#endif
|
|
2486
1661
|
}
|
|
2487
1662
|
|
|
2488
1663
|
public static Func<TInstance, T1, T2, T3, TReturn> GetInstanceMethodInvoker<
|
|
@@ -2497,20 +1672,9 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
2497
1672
|
method,
|
|
2498
1673
|
new[] { typeof(T1), typeof(T2), typeof(T3) }
|
|
2499
1674
|
);
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
{
|
|
2503
|
-
del = BuildInstanceInvoker3<TInstance, T1, T2, T3, TReturn>(method);
|
|
2504
|
-
TypedInstanceInvoker3[method] = del;
|
|
2505
|
-
}
|
|
2506
|
-
return (Func<TInstance, T1, T2, T3, TReturn>)del;
|
|
2507
|
-
#else
|
|
2508
|
-
Delegate del = TypedInstanceInvoker3.GetOrAdd(
|
|
2509
|
-
method,
|
|
2510
|
-
m => BuildInstanceInvoker3<TInstance, T1, T2, T3, TReturn>(m)
|
|
1675
|
+
return DelegateFactory.GetInstanceMethodInvokerTyped<TInstance, T1, T2, T3, TReturn>(
|
|
1676
|
+
method
|
|
2511
1677
|
);
|
|
2512
|
-
return (Func<TInstance, T1, T2, T3, TReturn>)del;
|
|
2513
|
-
#endif
|
|
2514
1678
|
}
|
|
2515
1679
|
|
|
2516
1680
|
public static Func<TInstance, T1, T2, T3, T4, TReturn> GetInstanceMethodInvoker<
|
|
@@ -2526,39 +1690,20 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
2526
1690
|
method,
|
|
2527
1691
|
new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) }
|
|
2528
1692
|
);
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
Delegate del = TypedInstanceInvoker4.GetOrAdd(
|
|
2538
|
-
method,
|
|
2539
|
-
m => BuildInstanceInvoker4<TInstance, T1, T2, T3, T4, TReturn>(m)
|
|
2540
|
-
);
|
|
2541
|
-
return (Func<TInstance, T1, T2, T3, T4, TReturn>)del;
|
|
2542
|
-
#endif
|
|
1693
|
+
return DelegateFactory.GetInstanceMethodInvokerTyped<
|
|
1694
|
+
TInstance,
|
|
1695
|
+
T1,
|
|
1696
|
+
T2,
|
|
1697
|
+
T3,
|
|
1698
|
+
T4,
|
|
1699
|
+
TReturn
|
|
1700
|
+
>(method);
|
|
2543
1701
|
}
|
|
2544
1702
|
|
|
2545
1703
|
public static Action<TInstance> GetInstanceActionInvoker<TInstance>(MethodInfo method)
|
|
2546
1704
|
{
|
|
2547
1705
|
ValidateInstanceActionSignature<TInstance>(method, Type.EmptyTypes);
|
|
2548
|
-
|
|
2549
|
-
if (!TypedInstanceAction0.TryGetValue(method, out Delegate del))
|
|
2550
|
-
{
|
|
2551
|
-
del = BuildInstanceActionInvoker0<TInstance>(method);
|
|
2552
|
-
TypedInstanceAction0[method] = del;
|
|
2553
|
-
}
|
|
2554
|
-
return (Action<TInstance>)del;
|
|
2555
|
-
#else
|
|
2556
|
-
Delegate del = TypedInstanceAction0.GetOrAdd(
|
|
2557
|
-
method,
|
|
2558
|
-
m => BuildInstanceActionInvoker0<TInstance>(m)
|
|
2559
|
-
);
|
|
2560
|
-
return (Action<TInstance>)del;
|
|
2561
|
-
#endif
|
|
1706
|
+
return DelegateFactory.GetInstanceActionInvokerTyped<TInstance>(method);
|
|
2562
1707
|
}
|
|
2563
1708
|
|
|
2564
1709
|
public static Action<TInstance, T1> GetInstanceActionInvoker<TInstance, T1>(
|
|
@@ -2566,20 +1711,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
2566
1711
|
)
|
|
2567
1712
|
{
|
|
2568
1713
|
ValidateInstanceActionSignature<TInstance>(method, new[] { typeof(T1) });
|
|
2569
|
-
|
|
2570
|
-
if (!TypedInstanceAction1.TryGetValue(method, out Delegate del))
|
|
2571
|
-
{
|
|
2572
|
-
del = BuildInstanceActionInvoker1<TInstance, T1>(method);
|
|
2573
|
-
TypedInstanceAction1[method] = del;
|
|
2574
|
-
}
|
|
2575
|
-
return (Action<TInstance, T1>)del;
|
|
2576
|
-
#else
|
|
2577
|
-
Delegate del = TypedInstanceAction1.GetOrAdd(
|
|
2578
|
-
method,
|
|
2579
|
-
m => BuildInstanceActionInvoker1<TInstance, T1>(m)
|
|
2580
|
-
);
|
|
2581
|
-
return (Action<TInstance, T1>)del;
|
|
2582
|
-
#endif
|
|
1714
|
+
return DelegateFactory.GetInstanceActionInvokerTyped<TInstance, T1>(method);
|
|
2583
1715
|
}
|
|
2584
1716
|
|
|
2585
1717
|
public static Action<TInstance, T1, T2> GetInstanceActionInvoker<TInstance, T1, T2>(
|
|
@@ -2587,20 +1719,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
2587
1719
|
)
|
|
2588
1720
|
{
|
|
2589
1721
|
ValidateInstanceActionSignature<TInstance>(method, new[] { typeof(T1), typeof(T2) });
|
|
2590
|
-
|
|
2591
|
-
if (!TypedInstanceAction2.TryGetValue(method, out Delegate del))
|
|
2592
|
-
{
|
|
2593
|
-
del = BuildInstanceActionInvoker2<TInstance, T1, T2>(method);
|
|
2594
|
-
TypedInstanceAction2[method] = del;
|
|
2595
|
-
}
|
|
2596
|
-
return (Action<TInstance, T1, T2>)del;
|
|
2597
|
-
#else
|
|
2598
|
-
Delegate del = TypedInstanceAction2.GetOrAdd(
|
|
2599
|
-
method,
|
|
2600
|
-
m => BuildInstanceActionInvoker2<TInstance, T1, T2>(m)
|
|
2601
|
-
);
|
|
2602
|
-
return (Action<TInstance, T1, T2>)del;
|
|
2603
|
-
#endif
|
|
1722
|
+
return DelegateFactory.GetInstanceActionInvokerTyped<TInstance, T1, T2>(method);
|
|
2604
1723
|
}
|
|
2605
1724
|
|
|
2606
1725
|
public static Action<TInstance, T1, T2, T3> GetInstanceActionInvoker<TInstance, T1, T2, T3>(
|
|
@@ -2611,20 +1730,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
2611
1730
|
method,
|
|
2612
1731
|
new[] { typeof(T1), typeof(T2), typeof(T3) }
|
|
2613
1732
|
);
|
|
2614
|
-
|
|
2615
|
-
if (!TypedInstanceAction3.TryGetValue(method, out Delegate del))
|
|
2616
|
-
{
|
|
2617
|
-
del = BuildInstanceActionInvoker3<TInstance, T1, T2, T3>(method);
|
|
2618
|
-
TypedInstanceAction3[method] = del;
|
|
2619
|
-
}
|
|
2620
|
-
return (Action<TInstance, T1, T2, T3>)del;
|
|
2621
|
-
#else
|
|
2622
|
-
Delegate del = TypedInstanceAction3.GetOrAdd(
|
|
2623
|
-
method,
|
|
2624
|
-
m => BuildInstanceActionInvoker3<TInstance, T1, T2, T3>(m)
|
|
2625
|
-
);
|
|
2626
|
-
return (Action<TInstance, T1, T2, T3>)del;
|
|
2627
|
-
#endif
|
|
1733
|
+
return DelegateFactory.GetInstanceActionInvokerTyped<TInstance, T1, T2, T3>(method);
|
|
2628
1734
|
}
|
|
2629
1735
|
|
|
2630
1736
|
public static Action<TInstance, T1, T2, T3, T4> GetInstanceActionInvoker<
|
|
@@ -2639,108 +1745,164 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
2639
1745
|
method,
|
|
2640
1746
|
new[] { typeof(T1), typeof(T2), typeof(T3), typeof(T4) }
|
|
2641
1747
|
);
|
|
2642
|
-
|
|
2643
|
-
if (!TypedInstanceAction4.TryGetValue(method, out Delegate del))
|
|
2644
|
-
{
|
|
2645
|
-
del = BuildInstanceActionInvoker4<TInstance, T1, T2, T3, T4>(method);
|
|
2646
|
-
TypedInstanceAction4[method] = del;
|
|
2647
|
-
}
|
|
2648
|
-
return (Action<TInstance, T1, T2, T3, T4>)del;
|
|
2649
|
-
#else
|
|
2650
|
-
Delegate del = TypedInstanceAction4.GetOrAdd(
|
|
2651
|
-
method,
|
|
2652
|
-
m => BuildInstanceActionInvoker4<TInstance, T1, T2, T3, T4>(m)
|
|
2653
|
-
);
|
|
2654
|
-
return (Action<TInstance, T1, T2, T3, T4>)del;
|
|
2655
|
-
#endif
|
|
1748
|
+
return DelegateFactory.GetInstanceActionInvokerTyped<TInstance, T1, T2, T3, T4>(method);
|
|
2656
1749
|
}
|
|
2657
1750
|
|
|
2658
1751
|
private static Delegate BuildTypedStaticInvoker2<T1, T2, TReturn>(MethodInfo method)
|
|
2659
1752
|
{
|
|
2660
|
-
|
|
1753
|
+
if (ExpressionsEnabled)
|
|
1754
|
+
{
|
|
1755
|
+
try
|
|
1756
|
+
{
|
|
1757
|
+
ParameterExpression p1 = Expression.Parameter(typeof(T1), "a");
|
|
1758
|
+
ParameterExpression p2 = Expression.Parameter(typeof(T2), "b");
|
|
1759
|
+
MethodCallExpression call = Expression.Call(method, p1, p2);
|
|
1760
|
+
return Expression.Lambda<Func<T1, T2, TReturn>>(call, p1, p2).Compile();
|
|
1761
|
+
}
|
|
1762
|
+
catch
|
|
1763
|
+
{
|
|
1764
|
+
// continue to alternative strategies
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
|
|
1768
|
+
#if EMIT_DYNAMIC_IL
|
|
1769
|
+
if (DynamicIlEnabled)
|
|
1770
|
+
{
|
|
1771
|
+
try
|
|
1772
|
+
{
|
|
1773
|
+
DynamicMethod dm = new(
|
|
1774
|
+
$"InvokeStatic2_{method.DeclaringType?.Name}_{method.Name}",
|
|
1775
|
+
typeof(TReturn),
|
|
1776
|
+
new[] { typeof(T1), typeof(T2) },
|
|
1777
|
+
method.Module,
|
|
1778
|
+
true
|
|
1779
|
+
);
|
|
1780
|
+
ILGenerator il = dm.GetILGenerator();
|
|
1781
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
1782
|
+
il.Emit(OpCodes.Ldarg_1);
|
|
1783
|
+
il.Emit(OpCodes.Call, method);
|
|
1784
|
+
il.Emit(OpCodes.Ret);
|
|
1785
|
+
return dm.CreateDelegate(typeof(Func<T1, T2, TReturn>));
|
|
1786
|
+
}
|
|
1787
|
+
catch
|
|
1788
|
+
{
|
|
1789
|
+
// ignore and fall back to reflection
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
#endif
|
|
1793
|
+
|
|
2661
1794
|
try
|
|
2662
1795
|
{
|
|
2663
1796
|
return method.CreateDelegate(typeof(Func<T1, T2, TReturn>));
|
|
2664
1797
|
}
|
|
2665
1798
|
catch
|
|
2666
1799
|
{
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
MethodCallExpression call = Expression.Call(method, p1, p2);
|
|
2671
|
-
return Expression.Lambda<Func<T1, T2, TReturn>>(call, p1, p2).Compile();
|
|
1800
|
+
return new Func<T1, T2, TReturn>(
|
|
1801
|
+
(a, b) => (TReturn)method.Invoke(null, new object[] { a, b })
|
|
1802
|
+
);
|
|
2672
1803
|
}
|
|
2673
|
-
#else
|
|
2674
|
-
DynamicMethod dm = new(
|
|
2675
|
-
$"InvokeStatic2_{method.DeclaringType?.Name}_{method.Name}",
|
|
2676
|
-
typeof(TReturn),
|
|
2677
|
-
new[] { typeof(T1), typeof(T2) },
|
|
2678
|
-
method.Module,
|
|
2679
|
-
true
|
|
2680
|
-
);
|
|
2681
|
-
ILGenerator il = dm.GetILGenerator();
|
|
2682
|
-
il.Emit(OpCodes.Ldarg_0);
|
|
2683
|
-
il.Emit(OpCodes.Ldarg_1);
|
|
2684
|
-
il.Emit(OpCodes.Call, method);
|
|
2685
|
-
il.Emit(OpCodes.Ret);
|
|
2686
|
-
return dm.CreateDelegate(typeof(Func<T1, T2, TReturn>));
|
|
2687
|
-
#endif
|
|
2688
1804
|
}
|
|
2689
1805
|
|
|
2690
1806
|
private static Delegate BuildTypedStaticInvoker0<TReturn>(MethodInfo method)
|
|
2691
1807
|
{
|
|
2692
|
-
|
|
1808
|
+
if (ExpressionsEnabled)
|
|
1809
|
+
{
|
|
1810
|
+
try
|
|
1811
|
+
{
|
|
1812
|
+
MethodCallExpression call = Expression.Call(method);
|
|
1813
|
+
return Expression.Lambda<Func<TReturn>>(call).Compile();
|
|
1814
|
+
}
|
|
1815
|
+
catch
|
|
1816
|
+
{
|
|
1817
|
+
// Fall through to alternative strategies
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
#if EMIT_DYNAMIC_IL
|
|
1822
|
+
if (DynamicIlEnabled)
|
|
1823
|
+
{
|
|
1824
|
+
try
|
|
1825
|
+
{
|
|
1826
|
+
DynamicMethod dm = new(
|
|
1827
|
+
$"InvokeStatic0_{method.DeclaringType?.Name}_{method.Name}",
|
|
1828
|
+
typeof(TReturn),
|
|
1829
|
+
Type.EmptyTypes,
|
|
1830
|
+
method.Module,
|
|
1831
|
+
true
|
|
1832
|
+
);
|
|
1833
|
+
ILGenerator il = dm.GetILGenerator();
|
|
1834
|
+
il.Emit(OpCodes.Call, method);
|
|
1835
|
+
il.Emit(OpCodes.Ret);
|
|
1836
|
+
return dm.CreateDelegate(typeof(Func<TReturn>));
|
|
1837
|
+
}
|
|
1838
|
+
catch
|
|
1839
|
+
{
|
|
1840
|
+
// Ignore and fall back to reflection
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1843
|
+
#endif
|
|
1844
|
+
|
|
2693
1845
|
try
|
|
2694
1846
|
{
|
|
2695
1847
|
return method.CreateDelegate(typeof(Func<TReturn>));
|
|
2696
1848
|
}
|
|
2697
1849
|
catch
|
|
2698
1850
|
{
|
|
2699
|
-
|
|
2700
|
-
return Expression.Lambda<Func<TReturn>>(call).Compile();
|
|
1851
|
+
return new Func<TReturn>(() => (TReturn)method.Invoke(null, Array.Empty<object>()));
|
|
2701
1852
|
}
|
|
2702
|
-
#else
|
|
2703
|
-
DynamicMethod dm = new(
|
|
2704
|
-
$"InvokeStatic0_{method.DeclaringType?.Name}_{method.Name}",
|
|
2705
|
-
typeof(TReturn),
|
|
2706
|
-
Type.EmptyTypes,
|
|
2707
|
-
method.Module,
|
|
2708
|
-
true
|
|
2709
|
-
);
|
|
2710
|
-
ILGenerator il = dm.GetILGenerator();
|
|
2711
|
-
il.Emit(OpCodes.Call, method);
|
|
2712
|
-
il.Emit(OpCodes.Ret);
|
|
2713
|
-
return dm.CreateDelegate(typeof(Func<TReturn>));
|
|
2714
|
-
#endif
|
|
2715
1853
|
}
|
|
2716
1854
|
|
|
2717
1855
|
private static Delegate BuildTypedStaticInvoker1<T1, TReturn>(MethodInfo method)
|
|
2718
1856
|
{
|
|
2719
|
-
|
|
1857
|
+
if (ExpressionsEnabled)
|
|
1858
|
+
{
|
|
1859
|
+
try
|
|
1860
|
+
{
|
|
1861
|
+
ParameterExpression a = Expression.Parameter(typeof(T1), "a");
|
|
1862
|
+
MethodCallExpression call = Expression.Call(method, a);
|
|
1863
|
+
return Expression.Lambda<Func<T1, TReturn>>(call, a).Compile();
|
|
1864
|
+
}
|
|
1865
|
+
catch
|
|
1866
|
+
{
|
|
1867
|
+
// Continue to alternative strategies
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
#if EMIT_DYNAMIC_IL
|
|
1872
|
+
if (DynamicIlEnabled)
|
|
1873
|
+
{
|
|
1874
|
+
try
|
|
1875
|
+
{
|
|
1876
|
+
DynamicMethod dm = new(
|
|
1877
|
+
$"InvokeStatic1_{method.DeclaringType?.Name}_{method.Name}",
|
|
1878
|
+
typeof(TReturn),
|
|
1879
|
+
new[] { typeof(T1) },
|
|
1880
|
+
method.Module,
|
|
1881
|
+
true
|
|
1882
|
+
);
|
|
1883
|
+
ILGenerator il = dm.GetILGenerator();
|
|
1884
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
1885
|
+
il.Emit(OpCodes.Call, method);
|
|
1886
|
+
il.Emit(OpCodes.Ret);
|
|
1887
|
+
return dm.CreateDelegate(typeof(Func<T1, TReturn>));
|
|
1888
|
+
}
|
|
1889
|
+
catch
|
|
1890
|
+
{
|
|
1891
|
+
// fall through
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
#endif
|
|
1895
|
+
|
|
2720
1896
|
try
|
|
2721
1897
|
{
|
|
2722
1898
|
return method.CreateDelegate(typeof(Func<T1, TReturn>));
|
|
2723
1899
|
}
|
|
2724
1900
|
catch
|
|
2725
1901
|
{
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
1902
|
+
return new Func<T1, TReturn>(arg =>
|
|
1903
|
+
(TReturn)method.Invoke(null, new object[] { arg })
|
|
1904
|
+
);
|
|
2729
1905
|
}
|
|
2730
|
-
#else
|
|
2731
|
-
DynamicMethod dm = new(
|
|
2732
|
-
$"InvokeStatic1_{method.DeclaringType?.Name}_{method.Name}",
|
|
2733
|
-
typeof(TReturn),
|
|
2734
|
-
new[] { typeof(T1) },
|
|
2735
|
-
method.Module,
|
|
2736
|
-
true
|
|
2737
|
-
);
|
|
2738
|
-
ILGenerator il = dm.GetILGenerator();
|
|
2739
|
-
il.Emit(OpCodes.Ldarg_0);
|
|
2740
|
-
il.Emit(OpCodes.Call, method);
|
|
2741
|
-
il.Emit(OpCodes.Ret);
|
|
2742
|
-
return dm.CreateDelegate(typeof(Func<T1, TReturn>));
|
|
2743
|
-
#endif
|
|
2744
1906
|
}
|
|
2745
1907
|
|
|
2746
1908
|
private static Delegate BuildTypedStaticInvoker3<T1, T2, T3, TReturn>(MethodInfo method)
|
|
@@ -3557,24 +2719,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
3557
2719
|
$"Type {type.Name} does not have a parameterless constructor"
|
|
3558
2720
|
);
|
|
3559
2721
|
}
|
|
3560
|
-
|
|
3561
|
-
#if !EMIT_DYNAMIC_IL
|
|
3562
|
-
return CreateCompiledParameterlessConstructor<T>(constructor);
|
|
3563
|
-
#else
|
|
3564
|
-
DynamicMethod dynamicMethod = new(
|
|
3565
|
-
$"CreateParameterless{type.Name}",
|
|
3566
|
-
typeof(T),
|
|
3567
|
-
Type.EmptyTypes,
|
|
3568
|
-
type,
|
|
3569
|
-
true
|
|
3570
|
-
);
|
|
3571
|
-
|
|
3572
|
-
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
3573
|
-
il.Emit(OpCodes.Newobj, constructor);
|
|
3574
|
-
il.Emit(OpCodes.Ret);
|
|
3575
|
-
|
|
3576
|
-
return (Func<T>)dynamicMethod.CreateDelegate(typeof(Func<T>));
|
|
3577
|
-
#endif
|
|
2722
|
+
return DelegateFactory.GetParameterlessConstructorTyped<T>(constructor);
|
|
3578
2723
|
}
|
|
3579
2724
|
|
|
3580
2725
|
/// <summary>
|
|
@@ -3593,28 +2738,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
3593
2738
|
$"Type {constructedType.Name} does not have a parameterless constructor"
|
|
3594
2739
|
);
|
|
3595
2740
|
}
|
|
3596
|
-
|
|
3597
|
-
#if !EMIT_DYNAMIC_IL
|
|
3598
|
-
return CreateCompiledGenericParameterlessConstructor<T>(constructedType, constructor);
|
|
3599
|
-
#else
|
|
3600
|
-
DynamicMethod dynamicMethod = new(
|
|
3601
|
-
$"CreateGenericParameterless{constructedType.Name}",
|
|
3602
|
-
typeof(T),
|
|
3603
|
-
Type.EmptyTypes,
|
|
3604
|
-
constructedType,
|
|
3605
|
-
true
|
|
3606
|
-
);
|
|
3607
|
-
|
|
3608
|
-
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
3609
|
-
il.Emit(OpCodes.Newobj, constructor);
|
|
3610
|
-
if (constructedType.IsValueType && typeof(T) == typeof(object))
|
|
3611
|
-
{
|
|
3612
|
-
il.Emit(OpCodes.Box, constructedType);
|
|
3613
|
-
}
|
|
3614
|
-
il.Emit(OpCodes.Ret);
|
|
3615
|
-
|
|
3616
|
-
return (Func<T>)dynamicMethod.CreateDelegate(typeof(Func<T>));
|
|
3617
|
-
#endif
|
|
2741
|
+
return DelegateFactory.GetParameterlessConstructorTyped<T>(constructor);
|
|
3618
2742
|
}
|
|
3619
2743
|
|
|
3620
2744
|
/// <summary>
|
|
@@ -4010,7 +3134,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
4010
3134
|
FieldLookup[key] = field;
|
|
4011
3135
|
}
|
|
4012
3136
|
#else
|
|
4013
|
-
field = FieldLookup.GetOrAdd(key, k => k.type.GetField(k.name, k.flags));
|
|
3137
|
+
field = FieldLookup.GetOrAdd(key, static k => k.type.GetField(k.name, k.flags));
|
|
4014
3138
|
#endif
|
|
4015
3139
|
return field != null;
|
|
4016
3140
|
}
|
|
@@ -4040,7 +3164,10 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
4040
3164
|
PropertyLookup[key] = property;
|
|
4041
3165
|
}
|
|
4042
3166
|
#else
|
|
4043
|
-
property = PropertyLookup.GetOrAdd(
|
|
3167
|
+
property = PropertyLookup.GetOrAdd(
|
|
3168
|
+
key,
|
|
3169
|
+
static k => k.type.GetProperty(k.name, k.flags)
|
|
3170
|
+
);
|
|
4044
3171
|
#endif
|
|
4045
3172
|
return property != null;
|
|
4046
3173
|
}
|
|
@@ -4083,20 +3210,21 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
4083
3210
|
#else
|
|
4084
3211
|
method = MethodLookup.GetOrAdd(
|
|
4085
3212
|
key,
|
|
4086
|
-
|
|
3213
|
+
static (tuple, state) =>
|
|
4087
3214
|
{
|
|
4088
|
-
if (
|
|
3215
|
+
if (state.parameterTypes == null)
|
|
4089
3216
|
{
|
|
4090
|
-
return
|
|
3217
|
+
return tuple.type.GetMethod(state.methodName, tuple.flags);
|
|
4091
3218
|
}
|
|
4092
|
-
return
|
|
4093
|
-
|
|
4094
|
-
|
|
3219
|
+
return tuple.type.GetMethod(
|
|
3220
|
+
state.methodName,
|
|
3221
|
+
tuple.flags,
|
|
4095
3222
|
binder: null,
|
|
4096
|
-
types:
|
|
3223
|
+
types: state.parameterTypes,
|
|
4097
3224
|
modifiers: null
|
|
4098
3225
|
);
|
|
4099
|
-
}
|
|
3226
|
+
},
|
|
3227
|
+
(methodName: name, parameterTypes: paramTypes)
|
|
4100
3228
|
);
|
|
4101
3229
|
#endif
|
|
4102
3230
|
return method != null;
|
|
@@ -4165,11 +3293,32 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
4165
3293
|
|
|
4166
3294
|
#if SINGLE_THREADED
|
|
4167
3295
|
private static readonly Dictionary<Type, Func<object, bool>> EnabledPropertyGetters = new();
|
|
3296
|
+
|
|
3297
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
3298
|
+
private static Func<object, bool> GetEnabledPropertyGetterCached(Type componentType)
|
|
3299
|
+
{
|
|
3300
|
+
if (!EnabledPropertyGetters.TryGetValue(componentType, out Func<object, bool> getter))
|
|
3301
|
+
{
|
|
3302
|
+
getter = BuildEnabledPropertyGetter(componentType);
|
|
3303
|
+
EnabledPropertyGetters[componentType] = getter;
|
|
3304
|
+
}
|
|
3305
|
+
|
|
3306
|
+
return getter;
|
|
3307
|
+
}
|
|
4168
3308
|
#else
|
|
4169
3309
|
private static readonly ConcurrentDictionary<
|
|
4170
3310
|
Type,
|
|
4171
3311
|
Func<object, bool>
|
|
4172
3312
|
> EnabledPropertyGetters = new();
|
|
3313
|
+
|
|
3314
|
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
3315
|
+
private static Func<object, bool> GetEnabledPropertyGetterCached(Type componentType)
|
|
3316
|
+
{
|
|
3317
|
+
return EnabledPropertyGetters.GetOrAdd(
|
|
3318
|
+
componentType,
|
|
3319
|
+
static type => BuildEnabledPropertyGetter(type)
|
|
3320
|
+
);
|
|
3321
|
+
}
|
|
4173
3322
|
#endif
|
|
4174
3323
|
|
|
4175
3324
|
private static Func<object, bool> BuildEnabledPropertyGetter(Type type)
|
|
@@ -4228,7 +3377,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
4228
3377
|
Type type
|
|
4229
3378
|
)
|
|
4230
3379
|
{
|
|
4231
|
-
if (!
|
|
3380
|
+
if (!ExpressionsEnabled)
|
|
4232
3381
|
{
|
|
4233
3382
|
return CreateDelegateEnabledPropertyGetter(property, type)
|
|
4234
3383
|
?? (instance => (bool)property.GetValue(instance));
|
|
@@ -4302,10 +3451,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
4302
3451
|
}
|
|
4303
3452
|
|
|
4304
3453
|
Type componentType = component.GetType();
|
|
4305
|
-
Func<object, bool> enabledGetter =
|
|
4306
|
-
componentType,
|
|
4307
|
-
inputType => BuildEnabledPropertyGetter(inputType)
|
|
4308
|
-
);
|
|
3454
|
+
Func<object, bool> enabledGetter = GetEnabledPropertyGetterCached(componentType);
|
|
4309
3455
|
|
|
4310
3456
|
if (enabledGetter == null)
|
|
4311
3457
|
{
|
|
@@ -4606,9 +3752,202 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
4606
3752
|
}
|
|
4607
3753
|
}
|
|
4608
3754
|
|
|
4609
|
-
private static bool
|
|
3755
|
+
private static bool CheckDynamicIlSupport()
|
|
4610
3756
|
{
|
|
4611
|
-
#if !
|
|
3757
|
+
#if !EMIT_DYNAMIC_IL
|
|
3758
|
+
return false;
|
|
3759
|
+
#else
|
|
3760
|
+
try
|
|
3761
|
+
{
|
|
3762
|
+
DynamicMethod dynamicMethod = new(
|
|
3763
|
+
"UnityHelpersIlProbe",
|
|
3764
|
+
typeof(int),
|
|
3765
|
+
Type.EmptyTypes,
|
|
3766
|
+
typeof(ReflectionHelpers),
|
|
3767
|
+
true
|
|
3768
|
+
);
|
|
3769
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
3770
|
+
il.Emit(OpCodes.Ldc_I4_0);
|
|
3771
|
+
il.Emit(OpCodes.Ret);
|
|
3772
|
+
_ = ((Func<int>)dynamicMethod.CreateDelegate(typeof(Func<int>)))();
|
|
3773
|
+
return true;
|
|
3774
|
+
}
|
|
3775
|
+
catch
|
|
3776
|
+
{
|
|
3777
|
+
return false;
|
|
3778
|
+
}
|
|
3779
|
+
#endif
|
|
3780
|
+
}
|
|
3781
|
+
|
|
3782
|
+
#if EMIT_DYNAMIC_IL
|
|
3783
|
+
private static Func<object, object[], object> BuildMethodInvokerIL(MethodInfo method)
|
|
3784
|
+
{
|
|
3785
|
+
try
|
|
3786
|
+
{
|
|
3787
|
+
DynamicMethod dynamicMethod = new(
|
|
3788
|
+
$"Invoke{method.DeclaringType.Name}_{method.Name}",
|
|
3789
|
+
typeof(object),
|
|
3790
|
+
new[] { typeof(object), typeof(object[]) },
|
|
3791
|
+
method.DeclaringType,
|
|
3792
|
+
true
|
|
3793
|
+
);
|
|
3794
|
+
|
|
3795
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
3796
|
+
ParameterInfo[] parameters = method.GetParameters();
|
|
3797
|
+
|
|
3798
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
3799
|
+
il.Emit(
|
|
3800
|
+
method.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
|
|
3801
|
+
method.DeclaringType
|
|
3802
|
+
);
|
|
3803
|
+
|
|
3804
|
+
for (int i = 0; i < parameters.Length; i++)
|
|
3805
|
+
{
|
|
3806
|
+
il.Emit(OpCodes.Ldarg_1);
|
|
3807
|
+
il.Emit(OpCodes.Ldc_I4, i);
|
|
3808
|
+
il.Emit(OpCodes.Ldelem_Ref);
|
|
3809
|
+
|
|
3810
|
+
Type paramType = parameters[i].ParameterType;
|
|
3811
|
+
if (paramType.IsValueType)
|
|
3812
|
+
{
|
|
3813
|
+
il.Emit(OpCodes.Unbox_Any, paramType);
|
|
3814
|
+
}
|
|
3815
|
+
else
|
|
3816
|
+
{
|
|
3817
|
+
il.Emit(OpCodes.Castclass, paramType);
|
|
3818
|
+
}
|
|
3819
|
+
}
|
|
3820
|
+
|
|
3821
|
+
il.Emit(method.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt, method);
|
|
3822
|
+
|
|
3823
|
+
if (method.ReturnType == typeof(void))
|
|
3824
|
+
{
|
|
3825
|
+
il.Emit(OpCodes.Ldnull);
|
|
3826
|
+
}
|
|
3827
|
+
else if (method.ReturnType.IsValueType)
|
|
3828
|
+
{
|
|
3829
|
+
il.Emit(OpCodes.Box, method.ReturnType);
|
|
3830
|
+
}
|
|
3831
|
+
|
|
3832
|
+
il.Emit(OpCodes.Ret);
|
|
3833
|
+
|
|
3834
|
+
return (Func<object, object[], object>)
|
|
3835
|
+
dynamicMethod.CreateDelegate(typeof(Func<object, object[], object>));
|
|
3836
|
+
}
|
|
3837
|
+
catch
|
|
3838
|
+
{
|
|
3839
|
+
return null;
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
|
|
3843
|
+
private static Func<object[], object> BuildStaticMethodInvokerIL(MethodInfo method)
|
|
3844
|
+
{
|
|
3845
|
+
try
|
|
3846
|
+
{
|
|
3847
|
+
DynamicMethod dynamicMethod = new(
|
|
3848
|
+
$"InvokeStatic{method.DeclaringType.Name}_{method.Name}",
|
|
3849
|
+
typeof(object),
|
|
3850
|
+
new[] { typeof(object[]) },
|
|
3851
|
+
method.DeclaringType,
|
|
3852
|
+
true
|
|
3853
|
+
);
|
|
3854
|
+
|
|
3855
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
3856
|
+
ParameterInfo[] parameters = method.GetParameters();
|
|
3857
|
+
|
|
3858
|
+
for (int i = 0; i < parameters.Length; i++)
|
|
3859
|
+
{
|
|
3860
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
3861
|
+
il.Emit(OpCodes.Ldc_I4, i);
|
|
3862
|
+
il.Emit(OpCodes.Ldelem_Ref);
|
|
3863
|
+
|
|
3864
|
+
Type paramType = parameters[i].ParameterType;
|
|
3865
|
+
if (paramType.IsValueType)
|
|
3866
|
+
{
|
|
3867
|
+
il.Emit(OpCodes.Unbox_Any, paramType);
|
|
3868
|
+
}
|
|
3869
|
+
else
|
|
3870
|
+
{
|
|
3871
|
+
il.Emit(OpCodes.Castclass, paramType);
|
|
3872
|
+
}
|
|
3873
|
+
}
|
|
3874
|
+
|
|
3875
|
+
il.Emit(OpCodes.Call, method);
|
|
3876
|
+
|
|
3877
|
+
if (method.ReturnType == typeof(void))
|
|
3878
|
+
{
|
|
3879
|
+
il.Emit(OpCodes.Ldnull);
|
|
3880
|
+
}
|
|
3881
|
+
else if (method.ReturnType.IsValueType)
|
|
3882
|
+
{
|
|
3883
|
+
il.Emit(OpCodes.Box, method.ReturnType);
|
|
3884
|
+
}
|
|
3885
|
+
|
|
3886
|
+
il.Emit(OpCodes.Ret);
|
|
3887
|
+
|
|
3888
|
+
return (Func<object[], object>)
|
|
3889
|
+
dynamicMethod.CreateDelegate(typeof(Func<object[], object>));
|
|
3890
|
+
}
|
|
3891
|
+
catch
|
|
3892
|
+
{
|
|
3893
|
+
return null;
|
|
3894
|
+
}
|
|
3895
|
+
}
|
|
3896
|
+
|
|
3897
|
+
private static Func<object[], object> BuildConstructorIL(ConstructorInfo constructor)
|
|
3898
|
+
{
|
|
3899
|
+
try
|
|
3900
|
+
{
|
|
3901
|
+
DynamicMethod dynamicMethod = new(
|
|
3902
|
+
$"Create{constructor.DeclaringType.Name}",
|
|
3903
|
+
typeof(object),
|
|
3904
|
+
new[] { typeof(object[]) },
|
|
3905
|
+
constructor.DeclaringType,
|
|
3906
|
+
true
|
|
3907
|
+
);
|
|
3908
|
+
|
|
3909
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
3910
|
+
ParameterInfo[] parameters = constructor.GetParameters();
|
|
3911
|
+
|
|
3912
|
+
for (int i = 0; i < parameters.Length; i++)
|
|
3913
|
+
{
|
|
3914
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
3915
|
+
il.Emit(OpCodes.Ldc_I4, i);
|
|
3916
|
+
il.Emit(OpCodes.Ldelem_Ref);
|
|
3917
|
+
|
|
3918
|
+
Type paramType = parameters[i].ParameterType;
|
|
3919
|
+
if (paramType.IsValueType)
|
|
3920
|
+
{
|
|
3921
|
+
il.Emit(OpCodes.Unbox_Any, paramType);
|
|
3922
|
+
}
|
|
3923
|
+
else
|
|
3924
|
+
{
|
|
3925
|
+
il.Emit(OpCodes.Castclass, paramType);
|
|
3926
|
+
}
|
|
3927
|
+
}
|
|
3928
|
+
|
|
3929
|
+
il.Emit(OpCodes.Newobj, constructor);
|
|
3930
|
+
|
|
3931
|
+
if (constructor.DeclaringType.IsValueType)
|
|
3932
|
+
{
|
|
3933
|
+
il.Emit(OpCodes.Box, constructor.DeclaringType);
|
|
3934
|
+
}
|
|
3935
|
+
|
|
3936
|
+
il.Emit(OpCodes.Ret);
|
|
3937
|
+
|
|
3938
|
+
return (Func<object[], object>)
|
|
3939
|
+
dynamicMethod.CreateDelegate(typeof(Func<object[], object>));
|
|
3940
|
+
}
|
|
3941
|
+
catch
|
|
3942
|
+
{
|
|
3943
|
+
return null;
|
|
3944
|
+
}
|
|
3945
|
+
}
|
|
3946
|
+
#endif
|
|
3947
|
+
|
|
3948
|
+
private static bool CheckExpressionCompilationSupport()
|
|
3949
|
+
{
|
|
3950
|
+
#if !SUPPORT_EXPRESSION_COMPILE
|
|
4612
3951
|
return false;
|
|
4613
3952
|
#else
|
|
4614
3953
|
try
|
|
@@ -4631,7 +3970,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
4631
3970
|
MethodInfo addMethod
|
|
4632
3971
|
)
|
|
4633
3972
|
{
|
|
4634
|
-
if (!
|
|
3973
|
+
if (!ExpressionsEnabled)
|
|
4635
3974
|
{
|
|
4636
3975
|
return null;
|
|
4637
3976
|
}
|
|
@@ -4642,9 +3981,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
4642
3981
|
ParameterExpression valueParam = Expression.Parameter(typeof(object), "value");
|
|
4643
3982
|
|
|
4644
3983
|
Expression castSet = Expression.Convert(setParam, hashSetType);
|
|
4645
|
-
Expression castValue = elementType
|
|
4646
|
-
? Expression.Convert(valueParam, elementType)
|
|
4647
|
-
: Expression.Convert(valueParam, elementType);
|
|
3984
|
+
Expression castValue = Expression.Convert(valueParam, elementType);
|
|
4648
3985
|
|
|
4649
3986
|
MethodCallExpression call = Expression.Call(castSet, addMethod, castValue);
|
|
4650
3987
|
Expression body =
|
|
@@ -4664,7 +4001,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
4664
4001
|
|
|
4665
4002
|
private static Func<object, object[], object> CreateCompiledMethodInvoker(MethodInfo method)
|
|
4666
4003
|
{
|
|
4667
|
-
if (!
|
|
4004
|
+
if (!ExpressionsEnabled)
|
|
4668
4005
|
{
|
|
4669
4006
|
return CreateDelegateMethodInvoker(method)
|
|
4670
4007
|
?? ((instance, args) => method.Invoke(instance, args));
|
|
@@ -4726,7 +4063,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
4726
4063
|
|
|
4727
4064
|
private static Func<object[], object> CreateCompiledStaticMethodInvoker(MethodInfo method)
|
|
4728
4065
|
{
|
|
4729
|
-
if (!
|
|
4066
|
+
if (!ExpressionsEnabled)
|
|
4730
4067
|
{
|
|
4731
4068
|
return CreateDelegateStaticMethodInvoker(method)
|
|
4732
4069
|
?? (args => method.Invoke(null, args));
|
|
@@ -4772,7 +4109,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
4772
4109
|
|
|
4773
4110
|
private static Func<object[], object> CreateCompiledConstructor(ConstructorInfo constructor)
|
|
4774
4111
|
{
|
|
4775
|
-
if (!
|
|
4112
|
+
if (!ExpressionsEnabled)
|
|
4776
4113
|
{
|
|
4777
4114
|
return CreateDelegateConstructor(constructor) ?? (args => constructor.Invoke(args));
|
|
4778
4115
|
}
|
|
@@ -4802,140 +4139,1185 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
4802
4139
|
? Expression.Convert(newExpression, typeof(object))
|
|
4803
4140
|
: newExpression;
|
|
4804
4141
|
|
|
4805
|
-
return Expression
|
|
4806
|
-
.Lambda<Func<object[], object>>(returnExpression, argsParam)
|
|
4807
|
-
.Compile();
|
|
4808
|
-
}
|
|
4809
|
-
catch
|
|
4810
|
-
{
|
|
4811
|
-
return args => constructor.Invoke(args);
|
|
4142
|
+
return Expression
|
|
4143
|
+
.Lambda<Func<object[], object>>(returnExpression, argsParam)
|
|
4144
|
+
.Compile();
|
|
4145
|
+
}
|
|
4146
|
+
catch
|
|
4147
|
+
{
|
|
4148
|
+
return args => constructor.Invoke(args);
|
|
4149
|
+
}
|
|
4150
|
+
}
|
|
4151
|
+
|
|
4152
|
+
private static Func<object> CreateCompiledParameterlessConstructor(
|
|
4153
|
+
ConstructorInfo constructor
|
|
4154
|
+
)
|
|
4155
|
+
{
|
|
4156
|
+
if (!ExpressionsEnabled)
|
|
4157
|
+
{
|
|
4158
|
+
return CreateDelegateParameterlessConstructor(constructor)
|
|
4159
|
+
?? (() => constructor.Invoke(null));
|
|
4160
|
+
}
|
|
4161
|
+
|
|
4162
|
+
try
|
|
4163
|
+
{
|
|
4164
|
+
Expression newExpression = Expression.New(constructor);
|
|
4165
|
+
Expression body = constructor.DeclaringType.IsValueType
|
|
4166
|
+
? Expression.Convert(newExpression, typeof(object))
|
|
4167
|
+
: newExpression;
|
|
4168
|
+
|
|
4169
|
+
return Expression.Lambda<Func<object>>(body).Compile();
|
|
4170
|
+
}
|
|
4171
|
+
catch
|
|
4172
|
+
{
|
|
4173
|
+
return CreateDelegateParameterlessConstructor(constructor)
|
|
4174
|
+
?? (() => constructor.Invoke(null));
|
|
4175
|
+
}
|
|
4176
|
+
}
|
|
4177
|
+
|
|
4178
|
+
private static Func<T> CreateCompiledParameterlessConstructor<T>(
|
|
4179
|
+
ConstructorInfo constructor,
|
|
4180
|
+
Type constructedType
|
|
4181
|
+
)
|
|
4182
|
+
{
|
|
4183
|
+
if (!ExpressionsEnabled)
|
|
4184
|
+
{
|
|
4185
|
+
if (constructedType == typeof(T))
|
|
4186
|
+
{
|
|
4187
|
+
return CreateDelegateParameterlessConstructor<T>(constructor)
|
|
4188
|
+
?? (() => (T)constructor.Invoke(null));
|
|
4189
|
+
}
|
|
4190
|
+
|
|
4191
|
+
return () => (T)constructor.Invoke(null);
|
|
4192
|
+
}
|
|
4193
|
+
|
|
4194
|
+
try
|
|
4195
|
+
{
|
|
4196
|
+
Expression newExpression = Expression.New(constructor);
|
|
4197
|
+
Expression body =
|
|
4198
|
+
constructedType.IsValueType && typeof(T) != constructedType
|
|
4199
|
+
? Expression.Convert(newExpression, typeof(T))
|
|
4200
|
+
: constructedType == typeof(T) ? newExpression
|
|
4201
|
+
: Expression.Convert(newExpression, typeof(T));
|
|
4202
|
+
|
|
4203
|
+
return Expression.Lambda<Func<T>>(body).Compile();
|
|
4204
|
+
}
|
|
4205
|
+
catch
|
|
4206
|
+
{
|
|
4207
|
+
return () => (T)constructor.Invoke(null);
|
|
4208
|
+
}
|
|
4209
|
+
}
|
|
4210
|
+
|
|
4211
|
+
private static Func<object, object[], object> CreateCompiledIndexerGetter(
|
|
4212
|
+
PropertyInfo property
|
|
4213
|
+
)
|
|
4214
|
+
{
|
|
4215
|
+
if (!ExpressionsEnabled)
|
|
4216
|
+
{
|
|
4217
|
+
return null;
|
|
4218
|
+
}
|
|
4219
|
+
|
|
4220
|
+
try
|
|
4221
|
+
{
|
|
4222
|
+
ParameterExpression instanceParam = Expression.Parameter(
|
|
4223
|
+
typeof(object),
|
|
4224
|
+
"instance"
|
|
4225
|
+
);
|
|
4226
|
+
ParameterExpression argsParam = Expression.Parameter(typeof(object[]), "args");
|
|
4227
|
+
|
|
4228
|
+
MethodInfo getMethod = property.GetGetMethod(true);
|
|
4229
|
+
if (getMethod == null)
|
|
4230
|
+
{
|
|
4231
|
+
return null;
|
|
4232
|
+
}
|
|
4233
|
+
|
|
4234
|
+
Expression targetExpression = property.DeclaringType.IsValueType
|
|
4235
|
+
? Expression.Unbox(instanceParam, property.DeclaringType)
|
|
4236
|
+
: Expression.Convert(instanceParam, property.DeclaringType);
|
|
4237
|
+
|
|
4238
|
+
ParameterInfo[] indices = property.GetIndexParameters();
|
|
4239
|
+
Expression[] indexExpressions = new Expression[indices.Length];
|
|
4240
|
+
for (int i = 0; i < indices.Length; i++)
|
|
4241
|
+
{
|
|
4242
|
+
Expression element = Expression.ArrayIndex(argsParam, Expression.Constant(i));
|
|
4243
|
+
Type indexType = indices[i].ParameterType;
|
|
4244
|
+
indexExpressions[i] = indexType.IsValueType
|
|
4245
|
+
? Expression.Unbox(element, indexType)
|
|
4246
|
+
: Expression.Convert(element, indexType);
|
|
4247
|
+
}
|
|
4248
|
+
|
|
4249
|
+
Expression propertyExpression = getMethod.IsStatic
|
|
4250
|
+
? Expression.Property(null, property, indexExpressions)
|
|
4251
|
+
: Expression.Property(targetExpression, property, indexExpressions);
|
|
4252
|
+
|
|
4253
|
+
Expression body = property.PropertyType.IsValueType
|
|
4254
|
+
? Expression.Convert(propertyExpression, typeof(object))
|
|
4255
|
+
: propertyExpression;
|
|
4256
|
+
|
|
4257
|
+
return Expression
|
|
4258
|
+
.Lambda<Func<object, object[], object>>(body, instanceParam, argsParam)
|
|
4259
|
+
.Compile();
|
|
4260
|
+
}
|
|
4261
|
+
catch
|
|
4262
|
+
{
|
|
4263
|
+
return null;
|
|
4264
|
+
}
|
|
4265
|
+
}
|
|
4266
|
+
|
|
4267
|
+
private static Action<object, object, object[]> CreateCompiledIndexerSetter(
|
|
4268
|
+
PropertyInfo property
|
|
4269
|
+
)
|
|
4270
|
+
{
|
|
4271
|
+
if (!ExpressionsEnabled)
|
|
4272
|
+
{
|
|
4273
|
+
return null;
|
|
4274
|
+
}
|
|
4275
|
+
|
|
4276
|
+
try
|
|
4277
|
+
{
|
|
4278
|
+
MethodInfo setMethod = property.GetSetMethod(true);
|
|
4279
|
+
if (setMethod == null)
|
|
4280
|
+
{
|
|
4281
|
+
return null;
|
|
4282
|
+
}
|
|
4283
|
+
|
|
4284
|
+
ParameterExpression instanceParam = Expression.Parameter(
|
|
4285
|
+
typeof(object),
|
|
4286
|
+
"instance"
|
|
4287
|
+
);
|
|
4288
|
+
ParameterExpression valueParam = Expression.Parameter(typeof(object), "value");
|
|
4289
|
+
ParameterExpression argsParam = Expression.Parameter(typeof(object[]), "args");
|
|
4290
|
+
|
|
4291
|
+
Expression targetExpression = property.DeclaringType.IsValueType
|
|
4292
|
+
? Expression.Unbox(instanceParam, property.DeclaringType)
|
|
4293
|
+
: Expression.Convert(instanceParam, property.DeclaringType);
|
|
4294
|
+
|
|
4295
|
+
ParameterInfo[] indices = property.GetIndexParameters();
|
|
4296
|
+
Expression[] indexExpressions = new Expression[indices.Length];
|
|
4297
|
+
for (int i = 0; i < indices.Length; i++)
|
|
4298
|
+
{
|
|
4299
|
+
Expression element = Expression.ArrayIndex(argsParam, Expression.Constant(i));
|
|
4300
|
+
Type indexType = indices[i].ParameterType;
|
|
4301
|
+
indexExpressions[i] = indexType.IsValueType
|
|
4302
|
+
? Expression.Unbox(element, indexType)
|
|
4303
|
+
: Expression.Convert(element, indexType);
|
|
4304
|
+
}
|
|
4305
|
+
|
|
4306
|
+
Expression valueExpression = property.PropertyType.IsValueType
|
|
4307
|
+
? Expression.Unbox(valueParam, property.PropertyType)
|
|
4308
|
+
: Expression.Convert(valueParam, property.PropertyType);
|
|
4309
|
+
|
|
4310
|
+
IEnumerable<Expression> arguments = indexExpressions.Concat(
|
|
4311
|
+
new[] { valueExpression }
|
|
4312
|
+
);
|
|
4313
|
+
Expression callExpression = setMethod.IsStatic
|
|
4314
|
+
? Expression.Call(setMethod, arguments)
|
|
4315
|
+
: Expression.Call(targetExpression, setMethod, arguments);
|
|
4316
|
+
|
|
4317
|
+
return Expression
|
|
4318
|
+
.Lambda<Action<object, object, object[]>>(
|
|
4319
|
+
callExpression,
|
|
4320
|
+
instanceParam,
|
|
4321
|
+
valueParam,
|
|
4322
|
+
argsParam
|
|
4323
|
+
)
|
|
4324
|
+
.Compile();
|
|
4325
|
+
}
|
|
4326
|
+
catch
|
|
4327
|
+
{
|
|
4328
|
+
return null;
|
|
4329
|
+
}
|
|
4330
|
+
}
|
|
4331
|
+
|
|
4332
|
+
private static Func<T> CreateCompiledParameterlessConstructor<T>(
|
|
4333
|
+
ConstructorInfo constructor
|
|
4334
|
+
)
|
|
4335
|
+
{
|
|
4336
|
+
return CreateCompiledParameterlessConstructor<T>(
|
|
4337
|
+
constructor,
|
|
4338
|
+
constructor.DeclaringType
|
|
4339
|
+
);
|
|
4340
|
+
}
|
|
4341
|
+
|
|
4342
|
+
private static Func<object, object> CreateCompiledFieldGetter(FieldInfo field)
|
|
4343
|
+
{
|
|
4344
|
+
try
|
|
4345
|
+
{
|
|
4346
|
+
ParameterExpression instanceParam = Expression.Parameter(
|
|
4347
|
+
typeof(object),
|
|
4348
|
+
"instance"
|
|
4349
|
+
);
|
|
4350
|
+
|
|
4351
|
+
Expression instanceExpression =
|
|
4352
|
+
field.IsStatic ? null
|
|
4353
|
+
: field.DeclaringType.IsValueType
|
|
4354
|
+
? Expression.Unbox(instanceParam, field.DeclaringType)
|
|
4355
|
+
: Expression.Convert(instanceParam, field.DeclaringType);
|
|
4356
|
+
|
|
4357
|
+
Expression fieldExpression = field.IsStatic
|
|
4358
|
+
? Expression.Field(null, field)
|
|
4359
|
+
: Expression.Field(instanceExpression, field);
|
|
4360
|
+
Expression returnExpression = field.FieldType.IsValueType
|
|
4361
|
+
? Expression.Convert(fieldExpression, typeof(object))
|
|
4362
|
+
: fieldExpression;
|
|
4363
|
+
|
|
4364
|
+
return Expression
|
|
4365
|
+
.Lambda<Func<object, object>>(returnExpression, instanceParam)
|
|
4366
|
+
.Compile();
|
|
4367
|
+
}
|
|
4368
|
+
catch
|
|
4369
|
+
{
|
|
4370
|
+
return null;
|
|
4371
|
+
}
|
|
4372
|
+
}
|
|
4373
|
+
|
|
4374
|
+
private static bool CanInlineAssignment(Type sourceType, Type targetType)
|
|
4375
|
+
{
|
|
4376
|
+
if (sourceType == targetType)
|
|
4377
|
+
{
|
|
4378
|
+
return true;
|
|
4379
|
+
}
|
|
4380
|
+
|
|
4381
|
+
if (!targetType.IsValueType)
|
|
4382
|
+
{
|
|
4383
|
+
if (sourceType.IsValueType)
|
|
4384
|
+
{
|
|
4385
|
+
return true;
|
|
4386
|
+
}
|
|
4387
|
+
|
|
4388
|
+
return targetType.IsAssignableFrom(sourceType);
|
|
4389
|
+
}
|
|
4390
|
+
|
|
4391
|
+
if (!sourceType.IsValueType)
|
|
4392
|
+
{
|
|
4393
|
+
return sourceType == typeof(object);
|
|
4394
|
+
}
|
|
4395
|
+
|
|
4396
|
+
return false;
|
|
4397
|
+
}
|
|
4398
|
+
|
|
4399
|
+
private static bool CanInlineReturnConversion(Type actualType, Type requestedType)
|
|
4400
|
+
{
|
|
4401
|
+
if (actualType == requestedType)
|
|
4402
|
+
{
|
|
4403
|
+
return true;
|
|
4404
|
+
}
|
|
4405
|
+
|
|
4406
|
+
if (requestedType.IsValueType)
|
|
4407
|
+
{
|
|
4408
|
+
if (!actualType.IsValueType)
|
|
4409
|
+
{
|
|
4410
|
+
return actualType == typeof(object);
|
|
4411
|
+
}
|
|
4412
|
+
|
|
4413
|
+
return false;
|
|
4414
|
+
}
|
|
4415
|
+
|
|
4416
|
+
if (actualType.IsValueType)
|
|
4417
|
+
{
|
|
4418
|
+
return true;
|
|
4419
|
+
}
|
|
4420
|
+
|
|
4421
|
+
return requestedType.IsAssignableFrom(actualType);
|
|
4422
|
+
}
|
|
4423
|
+
|
|
4424
|
+
private static Func<object, object> CreateCompiledPropertyGetter(PropertyInfo property)
|
|
4425
|
+
{
|
|
4426
|
+
try
|
|
4427
|
+
{
|
|
4428
|
+
MethodInfo getMethod = property.GetGetMethod(true);
|
|
4429
|
+
if (getMethod == null)
|
|
4430
|
+
{
|
|
4431
|
+
return property.GetValue;
|
|
4432
|
+
}
|
|
4433
|
+
|
|
4434
|
+
ParameterExpression instanceParam = Expression.Parameter(
|
|
4435
|
+
typeof(object),
|
|
4436
|
+
"instance"
|
|
4437
|
+
);
|
|
4438
|
+
Expression propertyExpression;
|
|
4439
|
+
|
|
4440
|
+
if (getMethod.IsStatic)
|
|
4441
|
+
{
|
|
4442
|
+
propertyExpression = Expression.Property(null, property);
|
|
4443
|
+
}
|
|
4444
|
+
else
|
|
4445
|
+
{
|
|
4446
|
+
Expression instanceExpression = property.DeclaringType.IsValueType
|
|
4447
|
+
? Expression.Unbox(instanceParam, property.DeclaringType)
|
|
4448
|
+
: Expression.Convert(instanceParam, property.DeclaringType);
|
|
4449
|
+
propertyExpression = Expression.Property(instanceExpression, property);
|
|
4450
|
+
}
|
|
4451
|
+
|
|
4452
|
+
Expression returnExpression = property.PropertyType.IsValueType
|
|
4453
|
+
? Expression.Convert(propertyExpression, typeof(object))
|
|
4454
|
+
: propertyExpression;
|
|
4455
|
+
|
|
4456
|
+
return Expression
|
|
4457
|
+
.Lambda<Func<object, object>>(returnExpression, instanceParam)
|
|
4458
|
+
.Compile();
|
|
4459
|
+
}
|
|
4460
|
+
catch
|
|
4461
|
+
{
|
|
4462
|
+
return property.GetValue;
|
|
4463
|
+
}
|
|
4464
|
+
}
|
|
4465
|
+
|
|
4466
|
+
private static Action<object, object> CreateCompiledPropertySetter(PropertyInfo property)
|
|
4467
|
+
{
|
|
4468
|
+
if (!ExpressionsEnabled)
|
|
4469
|
+
{
|
|
4470
|
+
return property.SetValue;
|
|
4471
|
+
}
|
|
4472
|
+
|
|
4473
|
+
try
|
|
4474
|
+
{
|
|
4475
|
+
MethodInfo setMethod = property.GetSetMethod(true);
|
|
4476
|
+
if (setMethod == null)
|
|
4477
|
+
{
|
|
4478
|
+
return property.SetValue;
|
|
4479
|
+
}
|
|
4480
|
+
|
|
4481
|
+
ParameterExpression instanceParam = Expression.Parameter(
|
|
4482
|
+
typeof(object),
|
|
4483
|
+
"instance"
|
|
4484
|
+
);
|
|
4485
|
+
ParameterExpression valueParam = Expression.Parameter(typeof(object), "value");
|
|
4486
|
+
|
|
4487
|
+
Expression valueExpression = property.PropertyType.IsValueType
|
|
4488
|
+
? Expression.Unbox(valueParam, property.PropertyType)
|
|
4489
|
+
: Expression.Convert(valueParam, property.PropertyType);
|
|
4490
|
+
|
|
4491
|
+
Expression callExpression;
|
|
4492
|
+
if (setMethod.IsStatic)
|
|
4493
|
+
{
|
|
4494
|
+
callExpression = Expression.Call(setMethod, valueExpression);
|
|
4495
|
+
}
|
|
4496
|
+
else
|
|
4497
|
+
{
|
|
4498
|
+
Expression instanceExpression = property.DeclaringType.IsValueType
|
|
4499
|
+
? Expression.Unbox(instanceParam, property.DeclaringType)
|
|
4500
|
+
: Expression.Convert(instanceParam, property.DeclaringType);
|
|
4501
|
+
callExpression = Expression.Call(
|
|
4502
|
+
instanceExpression,
|
|
4503
|
+
setMethod,
|
|
4504
|
+
valueExpression
|
|
4505
|
+
);
|
|
4506
|
+
}
|
|
4507
|
+
|
|
4508
|
+
return Expression
|
|
4509
|
+
.Lambda<Action<object, object>>(callExpression, instanceParam, valueParam)
|
|
4510
|
+
.Compile();
|
|
4511
|
+
}
|
|
4512
|
+
catch
|
|
4513
|
+
{
|
|
4514
|
+
return property.SetValue;
|
|
4515
|
+
}
|
|
4516
|
+
}
|
|
4517
|
+
|
|
4518
|
+
private static Func<TInstance, TValue> CreateCompiledTypedFieldGetter<TInstance, TValue>(
|
|
4519
|
+
FieldInfo field
|
|
4520
|
+
)
|
|
4521
|
+
{
|
|
4522
|
+
if (!ExpressionsEnabled)
|
|
4523
|
+
{
|
|
4524
|
+
return null;
|
|
4525
|
+
}
|
|
4526
|
+
|
|
4527
|
+
try
|
|
4528
|
+
{
|
|
4529
|
+
ParameterExpression instanceParam = Expression.Parameter(
|
|
4530
|
+
typeof(TInstance),
|
|
4531
|
+
"instance"
|
|
4532
|
+
);
|
|
4533
|
+
Expression fieldExpression;
|
|
4534
|
+
if (field.IsStatic)
|
|
4535
|
+
{
|
|
4536
|
+
fieldExpression = Expression.Field(null, field);
|
|
4537
|
+
}
|
|
4538
|
+
else
|
|
4539
|
+
{
|
|
4540
|
+
Expression instanceExpression = PrepareInstanceExpression(
|
|
4541
|
+
instanceParam,
|
|
4542
|
+
field.DeclaringType
|
|
4543
|
+
);
|
|
4544
|
+
fieldExpression = Expression.Field(instanceExpression, field);
|
|
4545
|
+
}
|
|
4546
|
+
|
|
4547
|
+
Expression body =
|
|
4548
|
+
field.FieldType == typeof(TValue)
|
|
4549
|
+
? fieldExpression
|
|
4550
|
+
: Expression.Convert(fieldExpression, typeof(TValue));
|
|
4551
|
+
|
|
4552
|
+
return Expression.Lambda<Func<TInstance, TValue>>(body, instanceParam).Compile();
|
|
4553
|
+
}
|
|
4554
|
+
catch
|
|
4555
|
+
{
|
|
4556
|
+
return null;
|
|
4557
|
+
}
|
|
4558
|
+
}
|
|
4559
|
+
|
|
4560
|
+
private static FieldSetter<TInstance, TValue> CreateCompiledTypedFieldSetter<
|
|
4561
|
+
TInstance,
|
|
4562
|
+
TValue
|
|
4563
|
+
>(FieldInfo field)
|
|
4564
|
+
{
|
|
4565
|
+
if (!ExpressionsEnabled)
|
|
4566
|
+
{
|
|
4567
|
+
return null;
|
|
4568
|
+
}
|
|
4569
|
+
|
|
4570
|
+
if (!field.IsStatic && typeof(TInstance) != field.DeclaringType)
|
|
4571
|
+
{
|
|
4572
|
+
return null;
|
|
4573
|
+
}
|
|
4574
|
+
|
|
4575
|
+
try
|
|
4576
|
+
{
|
|
4577
|
+
ParameterExpression instanceParam = Expression.Parameter(
|
|
4578
|
+
typeof(TInstance).MakeByRefType(),
|
|
4579
|
+
"instance"
|
|
4580
|
+
);
|
|
4581
|
+
ParameterExpression valueParam = Expression.Parameter(typeof(TValue), "value");
|
|
4582
|
+
|
|
4583
|
+
Expression valueExpression =
|
|
4584
|
+
field.FieldType == typeof(TValue)
|
|
4585
|
+
? valueParam
|
|
4586
|
+
: Expression.Convert(valueParam, field.FieldType);
|
|
4587
|
+
|
|
4588
|
+
Expression assignExpression;
|
|
4589
|
+
if (field.IsStatic)
|
|
4590
|
+
{
|
|
4591
|
+
assignExpression = Expression.Assign(
|
|
4592
|
+
Expression.Field(null, field),
|
|
4593
|
+
valueExpression
|
|
4594
|
+
);
|
|
4595
|
+
}
|
|
4596
|
+
else
|
|
4597
|
+
{
|
|
4598
|
+
Expression fieldAccess = Expression.Field(instanceParam, field);
|
|
4599
|
+
assignExpression = Expression.Assign(fieldAccess, valueExpression);
|
|
4600
|
+
}
|
|
4601
|
+
|
|
4602
|
+
return Expression
|
|
4603
|
+
.Lambda<FieldSetter<TInstance, TValue>>(
|
|
4604
|
+
assignExpression,
|
|
4605
|
+
instanceParam,
|
|
4606
|
+
valueParam
|
|
4607
|
+
)
|
|
4608
|
+
.Compile();
|
|
4609
|
+
}
|
|
4610
|
+
catch
|
|
4611
|
+
{
|
|
4612
|
+
return null;
|
|
4613
|
+
}
|
|
4614
|
+
}
|
|
4615
|
+
|
|
4616
|
+
private static Func<TValue> CreateCompiledTypedStaticFieldGetter<TValue>(FieldInfo field)
|
|
4617
|
+
{
|
|
4618
|
+
if (!ExpressionsEnabled)
|
|
4619
|
+
{
|
|
4620
|
+
return null;
|
|
4621
|
+
}
|
|
4622
|
+
|
|
4623
|
+
try
|
|
4624
|
+
{
|
|
4625
|
+
Expression body = Expression.Field(null, field);
|
|
4626
|
+
if (field.FieldType != typeof(TValue))
|
|
4627
|
+
{
|
|
4628
|
+
body = Expression.Convert(body, typeof(TValue));
|
|
4629
|
+
}
|
|
4630
|
+
|
|
4631
|
+
return Expression.Lambda<Func<TValue>>(body).Compile();
|
|
4632
|
+
}
|
|
4633
|
+
catch
|
|
4634
|
+
{
|
|
4635
|
+
return null;
|
|
4636
|
+
}
|
|
4637
|
+
}
|
|
4638
|
+
|
|
4639
|
+
private static Action<TValue> CreateCompiledTypedStaticFieldSetter<TValue>(FieldInfo field)
|
|
4640
|
+
{
|
|
4641
|
+
if (!ExpressionsEnabled)
|
|
4642
|
+
{
|
|
4643
|
+
return null;
|
|
4644
|
+
}
|
|
4645
|
+
|
|
4646
|
+
try
|
|
4647
|
+
{
|
|
4648
|
+
ParameterExpression valueParam = Expression.Parameter(typeof(TValue), "value");
|
|
4649
|
+
Expression valueExpression =
|
|
4650
|
+
field.FieldType == typeof(TValue)
|
|
4651
|
+
? valueParam
|
|
4652
|
+
: Expression.Convert(valueParam, field.FieldType);
|
|
4653
|
+
Expression assignExpression = Expression.Assign(
|
|
4654
|
+
Expression.Field(null, field),
|
|
4655
|
+
valueExpression
|
|
4656
|
+
);
|
|
4657
|
+
return Expression.Lambda<Action<TValue>>(assignExpression, valueParam).Compile();
|
|
4658
|
+
}
|
|
4659
|
+
catch
|
|
4660
|
+
{
|
|
4661
|
+
return null;
|
|
4662
|
+
}
|
|
4663
|
+
}
|
|
4664
|
+
|
|
4665
|
+
private static Func<TInstance, TValue> CreateCompiledTypedPropertyGetter<TInstance, TValue>(
|
|
4666
|
+
PropertyInfo property,
|
|
4667
|
+
MethodInfo getMethod
|
|
4668
|
+
)
|
|
4669
|
+
{
|
|
4670
|
+
if (!ExpressionsEnabled)
|
|
4671
|
+
{
|
|
4672
|
+
return null;
|
|
4673
|
+
}
|
|
4674
|
+
|
|
4675
|
+
try
|
|
4676
|
+
{
|
|
4677
|
+
ParameterExpression instanceParam = Expression.Parameter(
|
|
4678
|
+
typeof(TInstance),
|
|
4679
|
+
"instance"
|
|
4680
|
+
);
|
|
4681
|
+
|
|
4682
|
+
Expression callExpression;
|
|
4683
|
+
if (getMethod.IsStatic)
|
|
4684
|
+
{
|
|
4685
|
+
callExpression = Expression.Call(getMethod);
|
|
4686
|
+
}
|
|
4687
|
+
else
|
|
4688
|
+
{
|
|
4689
|
+
Expression instanceExpression = PrepareInstanceExpression(
|
|
4690
|
+
instanceParam,
|
|
4691
|
+
property.DeclaringType
|
|
4692
|
+
);
|
|
4693
|
+
callExpression = Expression.Call(instanceExpression, getMethod);
|
|
4694
|
+
}
|
|
4695
|
+
|
|
4696
|
+
Expression body =
|
|
4697
|
+
property.PropertyType == typeof(TValue)
|
|
4698
|
+
? callExpression
|
|
4699
|
+
: Expression.Convert(callExpression, typeof(TValue));
|
|
4700
|
+
|
|
4701
|
+
return Expression.Lambda<Func<TInstance, TValue>>(body, instanceParam).Compile();
|
|
4702
|
+
}
|
|
4703
|
+
catch
|
|
4704
|
+
{
|
|
4705
|
+
return null;
|
|
4706
|
+
}
|
|
4707
|
+
}
|
|
4708
|
+
|
|
4709
|
+
private static Action<TInstance, TValue> CreateCompiledTypedPropertySetter<
|
|
4710
|
+
TInstance,
|
|
4711
|
+
TValue
|
|
4712
|
+
>(PropertyInfo property, MethodInfo setMethod)
|
|
4713
|
+
{
|
|
4714
|
+
if (!ExpressionsEnabled)
|
|
4715
|
+
{
|
|
4716
|
+
return null;
|
|
4717
|
+
}
|
|
4718
|
+
|
|
4719
|
+
if (!setMethod.IsStatic && property.DeclaringType.IsValueType)
|
|
4720
|
+
{
|
|
4721
|
+
return null;
|
|
4722
|
+
}
|
|
4723
|
+
|
|
4724
|
+
try
|
|
4725
|
+
{
|
|
4726
|
+
ParameterExpression instanceParam = Expression.Parameter(
|
|
4727
|
+
typeof(TInstance),
|
|
4728
|
+
"instance"
|
|
4729
|
+
);
|
|
4730
|
+
ParameterExpression valueParam = Expression.Parameter(typeof(TValue), "value");
|
|
4731
|
+
|
|
4732
|
+
Expression valueExpression =
|
|
4733
|
+
property.PropertyType == typeof(TValue)
|
|
4734
|
+
? valueParam
|
|
4735
|
+
: Expression.Convert(valueParam, property.PropertyType);
|
|
4736
|
+
|
|
4737
|
+
MethodCallExpression callExpression;
|
|
4738
|
+
if (setMethod.IsStatic)
|
|
4739
|
+
{
|
|
4740
|
+
callExpression = Expression.Call(setMethod, valueExpression);
|
|
4741
|
+
}
|
|
4742
|
+
else
|
|
4743
|
+
{
|
|
4744
|
+
Expression instanceExpression = PrepareInstanceExpression(
|
|
4745
|
+
instanceParam,
|
|
4746
|
+
property.DeclaringType
|
|
4747
|
+
);
|
|
4748
|
+
callExpression = Expression.Call(
|
|
4749
|
+
instanceExpression,
|
|
4750
|
+
setMethod,
|
|
4751
|
+
valueExpression
|
|
4752
|
+
);
|
|
4753
|
+
}
|
|
4754
|
+
|
|
4755
|
+
return Expression
|
|
4756
|
+
.Lambda<Action<TInstance, TValue>>(callExpression, instanceParam, valueParam)
|
|
4757
|
+
.Compile();
|
|
4758
|
+
}
|
|
4759
|
+
catch
|
|
4760
|
+
{
|
|
4761
|
+
return null;
|
|
4762
|
+
}
|
|
4763
|
+
}
|
|
4764
|
+
|
|
4765
|
+
private static Func<TValue> CreateCompiledTypedStaticPropertyGetter<TValue>(
|
|
4766
|
+
PropertyInfo property,
|
|
4767
|
+
MethodInfo getMethod
|
|
4768
|
+
)
|
|
4769
|
+
{
|
|
4770
|
+
if (!ExpressionsEnabled)
|
|
4771
|
+
{
|
|
4772
|
+
return null;
|
|
4773
|
+
}
|
|
4774
|
+
|
|
4775
|
+
try
|
|
4776
|
+
{
|
|
4777
|
+
Expression body = Expression.Call(getMethod);
|
|
4778
|
+
if (property.PropertyType != typeof(TValue))
|
|
4779
|
+
{
|
|
4780
|
+
body = Expression.Convert(body, typeof(TValue));
|
|
4781
|
+
}
|
|
4782
|
+
|
|
4783
|
+
return Expression.Lambda<Func<TValue>>(body).Compile();
|
|
4784
|
+
}
|
|
4785
|
+
catch
|
|
4786
|
+
{
|
|
4787
|
+
return null;
|
|
4788
|
+
}
|
|
4789
|
+
}
|
|
4790
|
+
|
|
4791
|
+
private static Action<TValue> CreateCompiledTypedStaticPropertySetter<TValue>(
|
|
4792
|
+
PropertyInfo property,
|
|
4793
|
+
MethodInfo setMethod
|
|
4794
|
+
)
|
|
4795
|
+
{
|
|
4796
|
+
if (!ExpressionsEnabled)
|
|
4797
|
+
{
|
|
4798
|
+
return null;
|
|
4799
|
+
}
|
|
4800
|
+
|
|
4801
|
+
try
|
|
4802
|
+
{
|
|
4803
|
+
ParameterExpression valueParam = Expression.Parameter(typeof(TValue), "value");
|
|
4804
|
+
|
|
4805
|
+
Expression valueExpression =
|
|
4806
|
+
property.PropertyType == typeof(TValue)
|
|
4807
|
+
? valueParam
|
|
4808
|
+
: Expression.Convert(valueParam, property.PropertyType);
|
|
4809
|
+
|
|
4810
|
+
MethodCallExpression callExpression = Expression.Call(setMethod, valueExpression);
|
|
4811
|
+
|
|
4812
|
+
return Expression.Lambda<Action<TValue>>(callExpression, valueParam).Compile();
|
|
4813
|
+
}
|
|
4814
|
+
catch
|
|
4815
|
+
{
|
|
4816
|
+
return null;
|
|
4817
|
+
}
|
|
4818
|
+
}
|
|
4819
|
+
|
|
4820
|
+
private static Expression PrepareInstanceExpression(
|
|
4821
|
+
ParameterExpression instanceParameter,
|
|
4822
|
+
Type declaringType
|
|
4823
|
+
)
|
|
4824
|
+
{
|
|
4825
|
+
if (instanceParameter.Type == declaringType)
|
|
4826
|
+
{
|
|
4827
|
+
return instanceParameter;
|
|
4828
|
+
}
|
|
4829
|
+
|
|
4830
|
+
return Expression.Convert(instanceParameter, declaringType);
|
|
4831
|
+
}
|
|
4832
|
+
|
|
4833
|
+
#if EMIT_DYNAMIC_IL
|
|
4834
|
+
private static void EmitAssignmentConversion(
|
|
4835
|
+
ILGenerator il,
|
|
4836
|
+
Type sourceType,
|
|
4837
|
+
Type targetType
|
|
4838
|
+
)
|
|
4839
|
+
{
|
|
4840
|
+
if (targetType == sourceType)
|
|
4841
|
+
{
|
|
4842
|
+
return;
|
|
4843
|
+
}
|
|
4844
|
+
|
|
4845
|
+
if (targetType.IsValueType)
|
|
4846
|
+
{
|
|
4847
|
+
if (!sourceType.IsValueType)
|
|
4848
|
+
{
|
|
4849
|
+
il.Emit(OpCodes.Unbox_Any, targetType);
|
|
4850
|
+
}
|
|
4851
|
+
}
|
|
4852
|
+
else
|
|
4853
|
+
{
|
|
4854
|
+
if (sourceType.IsValueType)
|
|
4855
|
+
{
|
|
4856
|
+
il.Emit(OpCodes.Box, sourceType);
|
|
4857
|
+
if (targetType != typeof(object))
|
|
4858
|
+
{
|
|
4859
|
+
il.Emit(OpCodes.Castclass, targetType);
|
|
4860
|
+
}
|
|
4861
|
+
}
|
|
4862
|
+
else if (!targetType.IsAssignableFrom(sourceType))
|
|
4863
|
+
{
|
|
4864
|
+
il.Emit(OpCodes.Castclass, targetType);
|
|
4865
|
+
}
|
|
4866
|
+
}
|
|
4867
|
+
}
|
|
4868
|
+
|
|
4869
|
+
private static void EmitReturnConversion(
|
|
4870
|
+
ILGenerator il,
|
|
4871
|
+
Type actualType,
|
|
4872
|
+
Type requestedType
|
|
4873
|
+
)
|
|
4874
|
+
{
|
|
4875
|
+
if (requestedType == actualType)
|
|
4876
|
+
{
|
|
4877
|
+
return;
|
|
4878
|
+
}
|
|
4879
|
+
|
|
4880
|
+
if (requestedType.IsValueType)
|
|
4881
|
+
{
|
|
4882
|
+
if (!actualType.IsValueType)
|
|
4883
|
+
{
|
|
4884
|
+
il.Emit(OpCodes.Unbox_Any, requestedType);
|
|
4885
|
+
}
|
|
4886
|
+
}
|
|
4887
|
+
else
|
|
4888
|
+
{
|
|
4889
|
+
if (actualType.IsValueType)
|
|
4890
|
+
{
|
|
4891
|
+
il.Emit(OpCodes.Box, actualType);
|
|
4892
|
+
if (requestedType != typeof(object))
|
|
4893
|
+
{
|
|
4894
|
+
il.Emit(OpCodes.Castclass, requestedType);
|
|
4895
|
+
}
|
|
4896
|
+
}
|
|
4897
|
+
else if (!requestedType.IsAssignableFrom(actualType))
|
|
4898
|
+
{
|
|
4899
|
+
il.Emit(OpCodes.Castclass, requestedType);
|
|
4900
|
+
}
|
|
4901
|
+
}
|
|
4902
|
+
}
|
|
4903
|
+
|
|
4904
|
+
private static Func<object> BuildParameterlessConstructorIL(ConstructorInfo constructor)
|
|
4905
|
+
{
|
|
4906
|
+
DynamicMethod dynamicMethod = new(
|
|
4907
|
+
$"New_{constructor.DeclaringType.Name}_Obj",
|
|
4908
|
+
typeof(object),
|
|
4909
|
+
Type.EmptyTypes,
|
|
4910
|
+
constructor.DeclaringType,
|
|
4911
|
+
true
|
|
4912
|
+
);
|
|
4913
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
4914
|
+
il.Emit(OpCodes.Newobj, constructor);
|
|
4915
|
+
if (constructor.DeclaringType.IsValueType)
|
|
4916
|
+
{
|
|
4917
|
+
il.Emit(OpCodes.Box, constructor.DeclaringType);
|
|
4918
|
+
}
|
|
4919
|
+
il.Emit(OpCodes.Ret);
|
|
4920
|
+
return (Func<object>)dynamicMethod.CreateDelegate(typeof(Func<object>));
|
|
4921
|
+
}
|
|
4922
|
+
|
|
4923
|
+
private static Func<T> BuildTypedParameterlessConstructorIL<T>(ConstructorInfo constructor)
|
|
4924
|
+
{
|
|
4925
|
+
DynamicMethod dynamicMethod = new(
|
|
4926
|
+
$"New_{constructor.DeclaringType.Name}_{typeof(T).Name}",
|
|
4927
|
+
typeof(T),
|
|
4928
|
+
Type.EmptyTypes,
|
|
4929
|
+
constructor.DeclaringType,
|
|
4930
|
+
true
|
|
4931
|
+
);
|
|
4932
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
4933
|
+
il.Emit(OpCodes.Newobj, constructor);
|
|
4934
|
+
|
|
4935
|
+
Type declaringType = constructor.DeclaringType;
|
|
4936
|
+
if (declaringType != typeof(T))
|
|
4937
|
+
{
|
|
4938
|
+
if (declaringType.IsValueType)
|
|
4939
|
+
{
|
|
4940
|
+
il.Emit(OpCodes.Box, declaringType);
|
|
4941
|
+
if (typeof(T) != typeof(object))
|
|
4942
|
+
{
|
|
4943
|
+
il.Emit(OpCodes.Castclass, typeof(T));
|
|
4944
|
+
}
|
|
4945
|
+
}
|
|
4946
|
+
else if (!typeof(T).IsAssignableFrom(declaringType))
|
|
4947
|
+
{
|
|
4948
|
+
il.Emit(OpCodes.Castclass, typeof(T));
|
|
4949
|
+
}
|
|
4950
|
+
}
|
|
4951
|
+
|
|
4952
|
+
il.Emit(OpCodes.Ret);
|
|
4953
|
+
return (Func<T>)dynamicMethod.CreateDelegate(typeof(Func<T>));
|
|
4954
|
+
}
|
|
4955
|
+
|
|
4956
|
+
private static Func<object, object[], object> BuildIndexerGetterIL(PropertyInfo property)
|
|
4957
|
+
{
|
|
4958
|
+
MethodInfo getter =
|
|
4959
|
+
property.GetGetMethod(true)
|
|
4960
|
+
?? throw new ArgumentException("Indexer has no getter", nameof(property));
|
|
4961
|
+
|
|
4962
|
+
DynamicMethod dynamicMethod = new(
|
|
4963
|
+
$"GetIndexer_{property.DeclaringType.Name}_{property.Name}",
|
|
4964
|
+
typeof(object),
|
|
4965
|
+
new[] { typeof(object), typeof(object[]) },
|
|
4966
|
+
property.DeclaringType,
|
|
4967
|
+
true
|
|
4968
|
+
);
|
|
4969
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
4970
|
+
bool isStatic = getter.IsStatic;
|
|
4971
|
+
if (!isStatic)
|
|
4972
|
+
{
|
|
4973
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
4974
|
+
il.Emit(
|
|
4975
|
+
property.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
|
|
4976
|
+
property.DeclaringType
|
|
4977
|
+
);
|
|
4978
|
+
}
|
|
4979
|
+
|
|
4980
|
+
ParameterInfo[] indices = property.GetIndexParameters();
|
|
4981
|
+
for (int i = 0; i < indices.Length; i++)
|
|
4982
|
+
{
|
|
4983
|
+
il.Emit(OpCodes.Ldarg_1);
|
|
4984
|
+
il.Emit(OpCodes.Ldc_I4, i);
|
|
4985
|
+
il.Emit(OpCodes.Ldelem_Ref);
|
|
4986
|
+
EmitAssignmentConversion(il, typeof(object), indices[i].ParameterType);
|
|
4987
|
+
}
|
|
4988
|
+
|
|
4989
|
+
il.Emit(
|
|
4990
|
+
getter.IsStatic ? OpCodes.Call
|
|
4991
|
+
: property.DeclaringType.IsValueType ? OpCodes.Call
|
|
4992
|
+
: OpCodes.Callvirt,
|
|
4993
|
+
getter
|
|
4994
|
+
);
|
|
4995
|
+
EmitReturnConversion(il, property.PropertyType, typeof(object));
|
|
4996
|
+
il.Emit(OpCodes.Ret);
|
|
4997
|
+
return (Func<object, object[], object>)
|
|
4998
|
+
dynamicMethod.CreateDelegate(typeof(Func<object, object[], object>));
|
|
4999
|
+
}
|
|
5000
|
+
|
|
5001
|
+
private static Action<object, object, object[]> BuildIndexerSetterIL(PropertyInfo property)
|
|
5002
|
+
{
|
|
5003
|
+
MethodInfo setter =
|
|
5004
|
+
property.GetSetMethod(true)
|
|
5005
|
+
?? throw new ArgumentException("Indexer has no setter", nameof(property));
|
|
5006
|
+
|
|
5007
|
+
DynamicMethod dynamicMethod = new(
|
|
5008
|
+
$"SetIndexer_{property.DeclaringType.Name}_{property.Name}",
|
|
5009
|
+
typeof(void),
|
|
5010
|
+
new[] { typeof(object), typeof(object), typeof(object[]) },
|
|
5011
|
+
property.DeclaringType,
|
|
5012
|
+
true
|
|
5013
|
+
);
|
|
5014
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
5015
|
+
bool isStatic = setter.IsStatic;
|
|
5016
|
+
if (!isStatic)
|
|
5017
|
+
{
|
|
5018
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
5019
|
+
il.Emit(
|
|
5020
|
+
property.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
|
|
5021
|
+
property.DeclaringType
|
|
5022
|
+
);
|
|
5023
|
+
}
|
|
5024
|
+
|
|
5025
|
+
ParameterInfo[] indices = property.GetIndexParameters();
|
|
5026
|
+
for (int i = 0; i < indices.Length; i++)
|
|
5027
|
+
{
|
|
5028
|
+
il.Emit(OpCodes.Ldarg_2);
|
|
5029
|
+
il.Emit(OpCodes.Ldc_I4, i);
|
|
5030
|
+
il.Emit(OpCodes.Ldelem_Ref);
|
|
5031
|
+
EmitAssignmentConversion(il, typeof(object), indices[i].ParameterType);
|
|
5032
|
+
}
|
|
5033
|
+
|
|
5034
|
+
il.Emit(OpCodes.Ldarg_1);
|
|
5035
|
+
EmitAssignmentConversion(il, typeof(object), property.PropertyType);
|
|
5036
|
+
il.Emit(
|
|
5037
|
+
setter.IsStatic ? OpCodes.Call
|
|
5038
|
+
: property.DeclaringType.IsValueType ? OpCodes.Call
|
|
5039
|
+
: OpCodes.Callvirt,
|
|
5040
|
+
setter
|
|
5041
|
+
);
|
|
5042
|
+
il.Emit(OpCodes.Ret);
|
|
5043
|
+
return (Action<object, object, object[]>)
|
|
5044
|
+
dynamicMethod.CreateDelegate(typeof(Action<object, object, object[]>));
|
|
5045
|
+
}
|
|
5046
|
+
|
|
5047
|
+
private static Func<TInstance, TValue> BuildTypedFieldGetterIL<TInstance, TValue>(
|
|
5048
|
+
FieldInfo field
|
|
5049
|
+
)
|
|
5050
|
+
{
|
|
5051
|
+
DynamicMethod dynamicMethod = new(
|
|
5052
|
+
$"GetGeneric{field.DeclaringType.Name}_{field.Name}",
|
|
5053
|
+
typeof(TValue),
|
|
5054
|
+
new[] { typeof(TInstance) },
|
|
5055
|
+
field.DeclaringType,
|
|
5056
|
+
true
|
|
5057
|
+
);
|
|
5058
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
5059
|
+
|
|
5060
|
+
if (field.IsStatic)
|
|
5061
|
+
{
|
|
5062
|
+
il.Emit(OpCodes.Ldsfld, field);
|
|
5063
|
+
}
|
|
5064
|
+
else
|
|
5065
|
+
{
|
|
5066
|
+
if (typeof(TInstance).IsValueType)
|
|
5067
|
+
{
|
|
5068
|
+
il.Emit(OpCodes.Ldarga_S, 0);
|
|
5069
|
+
}
|
|
5070
|
+
else
|
|
5071
|
+
{
|
|
5072
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
5073
|
+
}
|
|
5074
|
+
|
|
5075
|
+
if (field.DeclaringType != typeof(TInstance))
|
|
5076
|
+
{
|
|
5077
|
+
il.Emit(
|
|
5078
|
+
field.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
|
|
5079
|
+
field.DeclaringType
|
|
5080
|
+
);
|
|
5081
|
+
}
|
|
5082
|
+
|
|
5083
|
+
il.Emit(OpCodes.Ldfld, field);
|
|
5084
|
+
}
|
|
5085
|
+
|
|
5086
|
+
EmitReturnConversion(il, field.FieldType, typeof(TValue));
|
|
5087
|
+
il.Emit(OpCodes.Ret);
|
|
5088
|
+
return (Func<TInstance, TValue>)
|
|
5089
|
+
dynamicMethod.CreateDelegate(typeof(Func<TInstance, TValue>));
|
|
5090
|
+
}
|
|
5091
|
+
|
|
5092
|
+
private static FieldSetter<TInstance, TValue> BuildTypedFieldSetterIL<TInstance, TValue>(
|
|
5093
|
+
FieldInfo field
|
|
5094
|
+
)
|
|
5095
|
+
{
|
|
5096
|
+
DynamicMethod dynamicMethod = new(
|
|
5097
|
+
$"SetFieldGeneric{field.DeclaringType.Name}_{field.Name}",
|
|
5098
|
+
typeof(void),
|
|
5099
|
+
new[] { typeof(TInstance).MakeByRefType(), typeof(TValue) },
|
|
5100
|
+
field.Module,
|
|
5101
|
+
true
|
|
5102
|
+
);
|
|
5103
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
5104
|
+
|
|
5105
|
+
if (field.IsStatic)
|
|
5106
|
+
{
|
|
5107
|
+
il.Emit(OpCodes.Ldarg_1);
|
|
5108
|
+
EmitAssignmentConversion(il, typeof(TValue), field.FieldType);
|
|
5109
|
+
il.Emit(OpCodes.Stsfld, field);
|
|
5110
|
+
}
|
|
5111
|
+
else
|
|
5112
|
+
{
|
|
5113
|
+
if (typeof(TInstance).IsValueType)
|
|
5114
|
+
{
|
|
5115
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
5116
|
+
}
|
|
5117
|
+
else
|
|
5118
|
+
{
|
|
5119
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
5120
|
+
il.Emit(OpCodes.Ldind_Ref);
|
|
5121
|
+
}
|
|
5122
|
+
|
|
5123
|
+
if (field.DeclaringType != typeof(TInstance))
|
|
5124
|
+
{
|
|
5125
|
+
il.Emit(
|
|
5126
|
+
field.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
|
|
5127
|
+
field.DeclaringType
|
|
5128
|
+
);
|
|
5129
|
+
}
|
|
5130
|
+
|
|
5131
|
+
il.Emit(OpCodes.Ldarg_1);
|
|
5132
|
+
EmitAssignmentConversion(il, typeof(TValue), field.FieldType);
|
|
5133
|
+
il.Emit(OpCodes.Stfld, field);
|
|
4812
5134
|
}
|
|
5135
|
+
|
|
5136
|
+
il.Emit(OpCodes.Ret);
|
|
5137
|
+
return (FieldSetter<TInstance, TValue>)
|
|
5138
|
+
dynamicMethod.CreateDelegate(typeof(FieldSetter<TInstance, TValue>));
|
|
4813
5139
|
}
|
|
4814
5140
|
|
|
4815
|
-
private static Func<
|
|
4816
|
-
ConstructorInfo constructor
|
|
4817
|
-
)
|
|
5141
|
+
private static Func<TValue> BuildTypedStaticFieldGetterIL<TValue>(FieldInfo field)
|
|
4818
5142
|
{
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
5143
|
+
DynamicMethod dynamicMethod = new(
|
|
5144
|
+
$"GetStaticTyped{field.DeclaringType.Name}_{field.Name}",
|
|
5145
|
+
typeof(TValue),
|
|
5146
|
+
Type.EmptyTypes,
|
|
5147
|
+
field.DeclaringType,
|
|
5148
|
+
true
|
|
5149
|
+
);
|
|
5150
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
5151
|
+
il.Emit(OpCodes.Ldsfld, field);
|
|
5152
|
+
EmitReturnConversion(il, field.FieldType, typeof(TValue));
|
|
5153
|
+
il.Emit(OpCodes.Ret);
|
|
5154
|
+
return (Func<TValue>)dynamicMethod.CreateDelegate(typeof(Func<TValue>));
|
|
5155
|
+
}
|
|
4824
5156
|
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4833
|
-
|
|
5157
|
+
private static Action<TValue> BuildTypedStaticFieldSetterIL<TValue>(FieldInfo field)
|
|
5158
|
+
{
|
|
5159
|
+
DynamicMethod dynamicMethod = new(
|
|
5160
|
+
$"SetStaticTyped{field.DeclaringType.Name}_{field.Name}",
|
|
5161
|
+
typeof(void),
|
|
5162
|
+
new[] { typeof(TValue) },
|
|
5163
|
+
field.Module,
|
|
5164
|
+
true
|
|
5165
|
+
);
|
|
5166
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
5167
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
5168
|
+
EmitAssignmentConversion(il, typeof(TValue), field.FieldType);
|
|
5169
|
+
il.Emit(OpCodes.Stsfld, field);
|
|
5170
|
+
il.Emit(OpCodes.Ret);
|
|
5171
|
+
return (Action<TValue>)dynamicMethod.CreateDelegate(typeof(Action<TValue>));
|
|
4834
5172
|
}
|
|
4835
5173
|
|
|
4836
|
-
private static Func<
|
|
4837
|
-
|
|
4838
|
-
|
|
5174
|
+
private static Func<TInstance, TValue> BuildTypedPropertyGetterIL<TInstance, TValue>(
|
|
5175
|
+
PropertyInfo property,
|
|
5176
|
+
MethodInfo getMethod
|
|
4839
5177
|
)
|
|
4840
5178
|
{
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
Expression newExpression = Expression.New(constructor);
|
|
4849
|
-
Expression convertExpression =
|
|
4850
|
-
constructedType.IsValueType && typeof(T) == typeof(object)
|
|
4851
|
-
? Expression.Convert(newExpression, typeof(object))
|
|
4852
|
-
: newExpression;
|
|
5179
|
+
DynamicMethod dynamicMethod = new(
|
|
5180
|
+
$"GetGeneric{property.DeclaringType.Name}_{property.Name}",
|
|
5181
|
+
typeof(TValue),
|
|
5182
|
+
new[] { typeof(TInstance) },
|
|
5183
|
+
property.DeclaringType,
|
|
5184
|
+
true
|
|
5185
|
+
);
|
|
4853
5186
|
|
|
4854
|
-
|
|
4855
|
-
}
|
|
4856
|
-
catch
|
|
4857
|
-
{
|
|
4858
|
-
return () => (T)Activator.CreateInstance(constructedType);
|
|
4859
|
-
}
|
|
4860
|
-
}
|
|
5187
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
4861
5188
|
|
|
4862
|
-
|
|
4863
|
-
{
|
|
4864
|
-
if (!CanCompileExpressions)
|
|
5189
|
+
if (getMethod.IsStatic)
|
|
4865
5190
|
{
|
|
4866
|
-
|
|
5191
|
+
il.Emit(OpCodes.Call, getMethod);
|
|
4867
5192
|
}
|
|
4868
|
-
|
|
4869
|
-
try
|
|
5193
|
+
else
|
|
4870
5194
|
{
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
5195
|
+
if (typeof(TInstance).IsValueType)
|
|
5196
|
+
{
|
|
5197
|
+
il.Emit(OpCodes.Ldarga_S, 0);
|
|
5198
|
+
}
|
|
5199
|
+
else
|
|
5200
|
+
{
|
|
5201
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
5202
|
+
}
|
|
4875
5203
|
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
5204
|
+
if (property.DeclaringType != typeof(TInstance))
|
|
5205
|
+
{
|
|
5206
|
+
il.Emit(
|
|
5207
|
+
property.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
|
|
5208
|
+
property.DeclaringType
|
|
5209
|
+
);
|
|
5210
|
+
}
|
|
4879
5211
|
|
|
4880
|
-
|
|
5212
|
+
il.Emit(
|
|
5213
|
+
property.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt,
|
|
5214
|
+
getMethod
|
|
5215
|
+
);
|
|
5216
|
+
}
|
|
4881
5217
|
|
|
4882
|
-
|
|
4883
|
-
? Expression.Convert(fieldExpression, typeof(object))
|
|
4884
|
-
: fieldExpression;
|
|
5218
|
+
EmitReturnConversion(il, property.PropertyType, typeof(TValue));
|
|
4885
5219
|
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
}
|
|
4890
|
-
catch
|
|
4891
|
-
{
|
|
4892
|
-
return field.GetValue;
|
|
4893
|
-
}
|
|
5220
|
+
il.Emit(OpCodes.Ret);
|
|
5221
|
+
return (Func<TInstance, TValue>)
|
|
5222
|
+
dynamicMethod.CreateDelegate(typeof(Func<TInstance, TValue>));
|
|
4894
5223
|
}
|
|
4895
5224
|
|
|
4896
|
-
private static
|
|
5225
|
+
private static Action<TInstance, TValue> BuildTypedPropertySetterIL<TInstance, TValue>(
|
|
5226
|
+
PropertyInfo property,
|
|
5227
|
+
MethodInfo setMethod
|
|
5228
|
+
)
|
|
4897
5229
|
{
|
|
4898
|
-
|
|
5230
|
+
DynamicMethod dynamicMethod = new(
|
|
5231
|
+
$"SetPropertyGeneric{property.DeclaringType.Name}_{property.Name}",
|
|
5232
|
+
typeof(void),
|
|
5233
|
+
new[] { typeof(TInstance), typeof(TValue) },
|
|
5234
|
+
property.DeclaringType,
|
|
5235
|
+
true
|
|
5236
|
+
);
|
|
5237
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
5238
|
+
|
|
5239
|
+
if (setMethod.IsStatic)
|
|
4899
5240
|
{
|
|
4900
|
-
|
|
5241
|
+
il.Emit(OpCodes.Ldarg_1);
|
|
5242
|
+
EmitAssignmentConversion(il, typeof(TValue), property.PropertyType);
|
|
5243
|
+
il.Emit(OpCodes.Call, setMethod);
|
|
4901
5244
|
}
|
|
4902
|
-
|
|
4903
|
-
try
|
|
5245
|
+
else
|
|
4904
5246
|
{
|
|
4905
|
-
|
|
4906
|
-
if (getMethod == null)
|
|
5247
|
+
if (typeof(TInstance).IsValueType)
|
|
4907
5248
|
{
|
|
4908
|
-
|
|
5249
|
+
il.Emit(OpCodes.Ldarga_S, 0);
|
|
5250
|
+
}
|
|
5251
|
+
else
|
|
5252
|
+
{
|
|
5253
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
5254
|
+
}
|
|
5255
|
+
if (property.DeclaringType != typeof(TInstance))
|
|
5256
|
+
{
|
|
5257
|
+
il.Emit(
|
|
5258
|
+
property.DeclaringType.IsValueType ? OpCodes.Unbox : OpCodes.Castclass,
|
|
5259
|
+
property.DeclaringType
|
|
5260
|
+
);
|
|
4909
5261
|
}
|
|
4910
5262
|
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
5263
|
+
il.Emit(OpCodes.Ldarg_1);
|
|
5264
|
+
EmitAssignmentConversion(il, typeof(TValue), property.PropertyType);
|
|
5265
|
+
|
|
5266
|
+
il.Emit(
|
|
5267
|
+
property.DeclaringType.IsValueType ? OpCodes.Call : OpCodes.Callvirt,
|
|
5268
|
+
setMethod
|
|
4914
5269
|
);
|
|
5270
|
+
}
|
|
4915
5271
|
|
|
4916
|
-
|
|
4917
|
-
|
|
4918
|
-
|
|
5272
|
+
il.Emit(OpCodes.Ret);
|
|
5273
|
+
return (Action<TInstance, TValue>)
|
|
5274
|
+
dynamicMethod.CreateDelegate(typeof(Action<TInstance, TValue>));
|
|
5275
|
+
}
|
|
4919
5276
|
|
|
4920
|
-
|
|
5277
|
+
private static Func<TValue> BuildTypedStaticPropertyGetterIL<TValue>(
|
|
5278
|
+
PropertyInfo property,
|
|
5279
|
+
MethodInfo getMethod
|
|
5280
|
+
)
|
|
5281
|
+
{
|
|
5282
|
+
DynamicMethod dynamicMethod = new(
|
|
5283
|
+
$"GetStaticTyped{property.DeclaringType.Name}_{property.Name}",
|
|
5284
|
+
typeof(TValue),
|
|
5285
|
+
Type.EmptyTypes,
|
|
5286
|
+
property.DeclaringType,
|
|
5287
|
+
true
|
|
5288
|
+
);
|
|
5289
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
5290
|
+
il.Emit(OpCodes.Call, getMethod);
|
|
5291
|
+
EmitReturnConversion(il, property.PropertyType, typeof(TValue));
|
|
4921
5292
|
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
5293
|
+
il.Emit(OpCodes.Ret);
|
|
5294
|
+
return (Func<TValue>)dynamicMethod.CreateDelegate(typeof(Func<TValue>));
|
|
5295
|
+
}
|
|
4925
5296
|
|
|
4926
|
-
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
5297
|
+
private static Action<TValue> BuildTypedStaticPropertySetterIL<TValue>(
|
|
5298
|
+
PropertyInfo property,
|
|
5299
|
+
MethodInfo setMethod
|
|
5300
|
+
)
|
|
5301
|
+
{
|
|
5302
|
+
DynamicMethod dynamicMethod = new(
|
|
5303
|
+
$"SetStaticTyped{property.DeclaringType.Name}_{property.Name}",
|
|
5304
|
+
typeof(void),
|
|
5305
|
+
new[] { typeof(TValue) },
|
|
5306
|
+
property.DeclaringType,
|
|
5307
|
+
true
|
|
5308
|
+
);
|
|
5309
|
+
ILGenerator il = dynamicMethod.GetILGenerator();
|
|
5310
|
+
il.Emit(OpCodes.Ldarg_0);
|
|
5311
|
+
EmitAssignmentConversion(il, typeof(TValue), property.PropertyType);
|
|
5312
|
+
il.Emit(OpCodes.Call, setMethod);
|
|
5313
|
+
il.Emit(OpCodes.Ret);
|
|
5314
|
+
return (Action<TValue>)dynamicMethod.CreateDelegate(typeof(Action<TValue>));
|
|
4934
5315
|
}
|
|
5316
|
+
#endif
|
|
4935
5317
|
|
|
4936
5318
|
private static Func<object> CreateCompiledStaticFieldGetter(FieldInfo field)
|
|
4937
5319
|
{
|
|
4938
|
-
if (!
|
|
5320
|
+
if (!ExpressionsEnabled)
|
|
4939
5321
|
{
|
|
4940
5322
|
return () => field.GetValue(null);
|
|
4941
5323
|
}
|
|
@@ -4958,7 +5340,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
4958
5340
|
|
|
4959
5341
|
private static Action<object, object> CreateCompiledFieldSetter(FieldInfo field)
|
|
4960
5342
|
{
|
|
4961
|
-
if (!
|
|
5343
|
+
if (!ExpressionsEnabled)
|
|
4962
5344
|
{
|
|
4963
5345
|
return field.SetValue;
|
|
4964
5346
|
}
|
|
@@ -4996,7 +5378,7 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
4996
5378
|
|
|
4997
5379
|
private static Action<object> CreateCompiledStaticFieldSetter(FieldInfo field)
|
|
4998
5380
|
{
|
|
4999
|
-
if (!
|
|
5381
|
+
if (!ExpressionsEnabled)
|
|
5000
5382
|
{
|
|
5001
5383
|
return value => field.SetValue(null, value);
|
|
5002
5384
|
}
|
|
@@ -5188,111 +5570,23 @@ namespace WallstopStudios.UnityHelpers.Core.Helper
|
|
|
5188
5570
|
}
|
|
5189
5571
|
}
|
|
5190
5572
|
|
|
5191
|
-
private static Func<object
|
|
5192
|
-
|
|
5193
|
-
|
|
5194
|
-
{
|
|
5195
|
-
if (field.IsStatic)
|
|
5196
|
-
{
|
|
5197
|
-
// For static fields, create a simple wrapper
|
|
5198
|
-
return instance => field.GetValue(null);
|
|
5199
|
-
}
|
|
5200
|
-
|
|
5201
|
-
// For instance fields, we can't easily create delegates, so use optimized wrapper
|
|
5202
|
-
return instance => field.GetValue(instance);
|
|
5203
|
-
}
|
|
5204
|
-
catch
|
|
5205
|
-
{
|
|
5206
|
-
return null;
|
|
5207
|
-
}
|
|
5208
|
-
}
|
|
5209
|
-
|
|
5210
|
-
private static Func<object, object> CreateDelegatePropertyGetter(PropertyInfo property)
|
|
5573
|
+
private static Func<object> CreateDelegateParameterlessConstructor(
|
|
5574
|
+
ConstructorInfo constructor
|
|
5575
|
+
)
|
|
5211
5576
|
{
|
|
5212
5577
|
try
|
|
5213
5578
|
{
|
|
5214
|
-
|
|
5215
|
-
if (getMethod == null)
|
|
5579
|
+
if (constructor.GetParameters().Length == 0)
|
|
5216
5580
|
{
|
|
5217
|
-
return null;
|
|
5581
|
+
return () => constructor.Invoke(null);
|
|
5218
5582
|
}
|
|
5219
5583
|
|
|
5220
|
-
if (getMethod.IsStatic)
|
|
5221
|
-
{
|
|
5222
|
-
Type funcType = typeof(Func<>).MakeGenericType(property.PropertyType);
|
|
5223
|
-
Delegate getter = Delegate.CreateDelegate(funcType, getMethod);
|
|
5224
|
-
return instance => getter.DynamicInvoke();
|
|
5225
|
-
}
|
|
5226
|
-
else
|
|
5227
|
-
{
|
|
5228
|
-
Type funcType = typeof(Func<,>).MakeGenericType(
|
|
5229
|
-
property.DeclaringType,
|
|
5230
|
-
property.PropertyType
|
|
5231
|
-
);
|
|
5232
|
-
Delegate getter = Delegate.CreateDelegate(funcType, getMethod);
|
|
5233
|
-
return instance => getter.DynamicInvoke(instance);
|
|
5234
|
-
}
|
|
5235
|
-
}
|
|
5236
|
-
catch
|
|
5237
|
-
{
|
|
5238
5584
|
return null;
|
|
5239
5585
|
}
|
|
5240
|
-
}
|
|
5241
|
-
|
|
5242
|
-
private static Func<object, object> CreateGenericFieldGetter(FieldInfo field)
|
|
5243
|
-
{
|
|
5244
|
-
try
|
|
5245
|
-
{
|
|
5246
|
-
// For now, just use direct field access - it's already reasonably fast
|
|
5247
|
-
if (field.IsStatic)
|
|
5248
|
-
{
|
|
5249
|
-
return instance => field.GetValue(null);
|
|
5250
|
-
}
|
|
5251
|
-
|
|
5252
|
-
return instance => field.GetValue(instance);
|
|
5253
|
-
}
|
|
5254
5586
|
catch
|
|
5255
5587
|
{
|
|
5256
5588
|
return null;
|
|
5257
5589
|
}
|
|
5258
5590
|
}
|
|
5259
|
-
|
|
5260
|
-
private static Type GetActionType(Type[] parameterTypes)
|
|
5261
|
-
{
|
|
5262
|
-
switch (parameterTypes.Length)
|
|
5263
|
-
{
|
|
5264
|
-
case 0:
|
|
5265
|
-
return typeof(Action);
|
|
5266
|
-
case 1:
|
|
5267
|
-
return typeof(Action<>).MakeGenericType(parameterTypes);
|
|
5268
|
-
case 2:
|
|
5269
|
-
return typeof(Action<,>).MakeGenericType(parameterTypes);
|
|
5270
|
-
case 3:
|
|
5271
|
-
return typeof(Action<,,>).MakeGenericType(parameterTypes);
|
|
5272
|
-
case 4:
|
|
5273
|
-
return typeof(Action<,,,>).MakeGenericType(parameterTypes);
|
|
5274
|
-
default:
|
|
5275
|
-
return null;
|
|
5276
|
-
}
|
|
5277
|
-
}
|
|
5278
|
-
|
|
5279
|
-
private static Type GetFuncType(Type[] typeArgs)
|
|
5280
|
-
{
|
|
5281
|
-
switch (typeArgs.Length)
|
|
5282
|
-
{
|
|
5283
|
-
case 1:
|
|
5284
|
-
return typeof(Func<>).MakeGenericType(typeArgs);
|
|
5285
|
-
case 2:
|
|
5286
|
-
return typeof(Func<,>).MakeGenericType(typeArgs);
|
|
5287
|
-
case 3:
|
|
5288
|
-
return typeof(Func<,,>).MakeGenericType(typeArgs);
|
|
5289
|
-
case 4:
|
|
5290
|
-
return typeof(Func<,,,>).MakeGenericType(typeArgs);
|
|
5291
|
-
case 5:
|
|
5292
|
-
return typeof(Func<,,,,>).MakeGenericType(typeArgs);
|
|
5293
|
-
default:
|
|
5294
|
-
return null;
|
|
5295
|
-
}
|
|
5296
|
-
}
|
|
5297
5591
|
}
|
|
5298
5592
|
}
|