com.wallstop-studios.unity-helpers 2.1.1 → 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 +16 -16
- package/Docs/INDEX.md +1 -0
- package/Docs/RANDOM_PERFORMANCE.md +15 -15
- package/Docs/REFLECTION_HELPERS.md +84 -1
- package/Docs/REFLECTION_PERFORMANCE.md +169 -0
- package/{package-lock.json.meta → Docs/REFLECTION_PERFORMANCE.md.meta} +1 -1
- 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/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 +8 -3
- 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/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/Math/Line2D.cs +2 -4
- package/Runtime/Core/Math/Line3D.cs +2 -4
- package/Runtime/Core/Random/FlurryBurstRandom.cs +0 -6
- package/Runtime/Tags/AttributeMetadataCache.cs +4 -6
- 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/Runtime/Helper/ObjectsTests.cs +1 -1
- 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/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/package.json +1 -1
- package/Tests/Runtime/Performance/RelationComponentPerformanceTests.cs +0 -60
- package/Tests/Runtime/Performance/RelationComponentPerformanceTests.cs.meta +0 -3
|
@@ -93,12 +93,24 @@ namespace WallstopStudios.UnityHelpers.Tests.Helper
|
|
|
93
93
|
return param * 2;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
public static int StaticMethodTwoParams(int a, int b)
|
|
97
|
+
{
|
|
98
|
+
StaticMethodCallCount++;
|
|
99
|
+
return a + b;
|
|
100
|
+
}
|
|
101
|
+
|
|
96
102
|
public int InstanceMethodWithParam(string param)
|
|
97
103
|
{
|
|
98
104
|
instanceMethodCallCount++;
|
|
99
105
|
return param?.Length ?? 0;
|
|
100
106
|
}
|
|
101
107
|
|
|
108
|
+
public int InstanceMethodThreeParams(int a, string b, bool c)
|
|
109
|
+
{
|
|
110
|
+
instanceMethodCallCount++;
|
|
111
|
+
return a + (b?.Length ?? 0) + (c ? 1 : 0);
|
|
112
|
+
}
|
|
113
|
+
|
|
102
114
|
public static void StaticVoidMethodWithParam(int param)
|
|
103
115
|
{
|
|
104
116
|
StaticMethodCallCount = param;
|
|
@@ -122,6 +134,16 @@ namespace WallstopStudios.UnityHelpers.Tests.Helper
|
|
|
122
134
|
StaticMethodCallCount = a + b + c;
|
|
123
135
|
}
|
|
124
136
|
|
|
137
|
+
public static void StaticActionTwo(int a, int b)
|
|
138
|
+
{
|
|
139
|
+
StaticMethodCallCount = a + b;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
public static void StaticActionFour(int a, int b, int c, int d)
|
|
143
|
+
{
|
|
144
|
+
StaticMethodCallCount = a + b + c + d;
|
|
145
|
+
}
|
|
146
|
+
|
|
125
147
|
public int InstanceSum(int a, int b)
|
|
126
148
|
{
|
|
127
149
|
instanceMethodCallCount++;
|
|
@@ -133,6 +155,21 @@ namespace WallstopStudios.UnityHelpers.Tests.Helper
|
|
|
133
155
|
instanceMethodCallCount = a + b + c;
|
|
134
156
|
}
|
|
135
157
|
|
|
158
|
+
public void InstanceSetOne(int value)
|
|
159
|
+
{
|
|
160
|
+
instanceMethodCallCount = value;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
public void InstanceSetTwo(int a, int b)
|
|
164
|
+
{
|
|
165
|
+
instanceMethodCallCount = a + b;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
public void InstanceSetFour(int a, int b, int c, int d)
|
|
169
|
+
{
|
|
170
|
+
instanceMethodCallCount = a + b + c + d;
|
|
171
|
+
}
|
|
172
|
+
|
|
136
173
|
public int InstanceSumFour(int a, int b, int c, int d)
|
|
137
174
|
{
|
|
138
175
|
instanceMethodCallCount++;
|
|
@@ -144,6 +181,11 @@ namespace WallstopStudios.UnityHelpers.Tests.Helper
|
|
|
144
181
|
StaticMethodCallCount = 0;
|
|
145
182
|
instanceMethodCallCount = 0;
|
|
146
183
|
}
|
|
184
|
+
|
|
185
|
+
public static void ResetStatic()
|
|
186
|
+
{
|
|
187
|
+
StaticMethodCallCount = 0;
|
|
188
|
+
}
|
|
147
189
|
}
|
|
148
190
|
|
|
149
191
|
public sealed class TestConstructorClass
|
|
@@ -217,6 +259,14 @@ namespace WallstopStudios.UnityHelpers.Tests.Helper
|
|
|
217
259
|
public int InstanceReadOnlyProperty => 888;
|
|
218
260
|
}
|
|
219
261
|
|
|
262
|
+
public sealed class VariantPropertyClass
|
|
263
|
+
{
|
|
264
|
+
public object ObjectProperty { get; set; } = "instance";
|
|
265
|
+
public static object StaticObjectProperty { get; set; } = "static";
|
|
266
|
+
public object ObjectField = "instance-field";
|
|
267
|
+
public static object StaticObjectField = "static-field";
|
|
268
|
+
}
|
|
269
|
+
|
|
220
270
|
public sealed class SelfReferentialType
|
|
221
271
|
{
|
|
222
272
|
public static SelfReferentialType InstanceField = new();
|
|
@@ -1795,6 +1845,616 @@ namespace WallstopStudios.UnityHelpers.Tests.Helper
|
|
|
1795
1845
|
Assert.AreEqual(777, getter(dummy));
|
|
1796
1846
|
}
|
|
1797
1847
|
|
|
1848
|
+
[Test]
|
|
1849
|
+
public void TypedPropertyGetterBoxesValueTypeWhenRequested()
|
|
1850
|
+
{
|
|
1851
|
+
PropertyInfo property = typeof(TestPropertyClass).GetProperty(
|
|
1852
|
+
nameof(TestPropertyClass.InstanceProperty)
|
|
1853
|
+
);
|
|
1854
|
+
Func<TestPropertyClass, object> getter = ReflectionHelpers.GetPropertyGetter<
|
|
1855
|
+
TestPropertyClass,
|
|
1856
|
+
object
|
|
1857
|
+
>(property);
|
|
1858
|
+
TestPropertyClass instance = new() { InstanceProperty = 512 };
|
|
1859
|
+
Assert.AreEqual(512, getter(instance));
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
[Test]
|
|
1863
|
+
public void TypedPropertySetterUnboxesValueTypes()
|
|
1864
|
+
{
|
|
1865
|
+
PropertyInfo property = typeof(TestPropertyClass).GetProperty(
|
|
1866
|
+
nameof(TestPropertyClass.InstanceProperty)
|
|
1867
|
+
);
|
|
1868
|
+
Action<TestPropertyClass, object> setter = ReflectionHelpers.GetPropertySetter<
|
|
1869
|
+
TestPropertyClass,
|
|
1870
|
+
object
|
|
1871
|
+
>(property);
|
|
1872
|
+
TestPropertyClass instance = new();
|
|
1873
|
+
setter(instance, 2048);
|
|
1874
|
+
Assert.AreEqual(2048, instance.InstanceProperty);
|
|
1875
|
+
}
|
|
1876
|
+
|
|
1877
|
+
[Test]
|
|
1878
|
+
public void TypedStaticPropertySetterUnboxesValueTypes()
|
|
1879
|
+
{
|
|
1880
|
+
PropertyInfo property = typeof(TestPropertyClass).GetProperty(
|
|
1881
|
+
nameof(TestPropertyClass.StaticProperty)
|
|
1882
|
+
);
|
|
1883
|
+
object original = TestPropertyClass.StaticProperty;
|
|
1884
|
+
try
|
|
1885
|
+
{
|
|
1886
|
+
Action<object> setter = ReflectionHelpers.GetStaticPropertySetter<object>(property);
|
|
1887
|
+
setter(1024);
|
|
1888
|
+
Assert.AreEqual(1024, TestPropertyClass.StaticProperty);
|
|
1889
|
+
}
|
|
1890
|
+
finally
|
|
1891
|
+
{
|
|
1892
|
+
TestPropertyClass.StaticProperty = (int)original;
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
|
|
1896
|
+
[Test]
|
|
1897
|
+
public void TypedPropertyGetterCastsReferenceTypes()
|
|
1898
|
+
{
|
|
1899
|
+
VariantPropertyClass instance = new() { ObjectProperty = "hello" };
|
|
1900
|
+
PropertyInfo property = typeof(VariantPropertyClass).GetProperty(
|
|
1901
|
+
nameof(VariantPropertyClass.ObjectProperty)
|
|
1902
|
+
);
|
|
1903
|
+
Func<VariantPropertyClass, string> getter = ReflectionHelpers.GetPropertyGetter<
|
|
1904
|
+
VariantPropertyClass,
|
|
1905
|
+
string
|
|
1906
|
+
>(property);
|
|
1907
|
+
Assert.AreEqual("hello", getter(instance));
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
[Test]
|
|
1911
|
+
public void DynamicIlBoxedFieldGetterReturnsValue()
|
|
1912
|
+
{
|
|
1913
|
+
RunWithDynamicIlOnly(() =>
|
|
1914
|
+
{
|
|
1915
|
+
TestClass instance = new() { intValue = 321 };
|
|
1916
|
+
FieldInfo field = typeof(TestClass).GetField(nameof(TestClass.intValue));
|
|
1917
|
+
Func<object, object> getter = ReflectionHelpers.GetFieldGetter(field);
|
|
1918
|
+
Assert.AreEqual(321, getter(instance));
|
|
1919
|
+
});
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
[Test]
|
|
1923
|
+
public void DynamicIlBoxedFieldSetterMutatesInstance()
|
|
1924
|
+
{
|
|
1925
|
+
RunWithDynamicIlOnly(() =>
|
|
1926
|
+
{
|
|
1927
|
+
TestClass instance = new();
|
|
1928
|
+
FieldInfo field = typeof(TestClass).GetField(nameof(TestClass.intValue));
|
|
1929
|
+
Action<object, object> setter = ReflectionHelpers.GetFieldSetter(field);
|
|
1930
|
+
setter(instance, 654);
|
|
1931
|
+
Assert.AreEqual(654, instance.intValue);
|
|
1932
|
+
});
|
|
1933
|
+
}
|
|
1934
|
+
|
|
1935
|
+
[Test]
|
|
1936
|
+
public void DynamicIlTypedFieldSetterMutatesInstance()
|
|
1937
|
+
{
|
|
1938
|
+
RunWithDynamicIlOnly(() =>
|
|
1939
|
+
{
|
|
1940
|
+
FieldInfo field = typeof(TestClass).GetField(nameof(TestClass.intValue));
|
|
1941
|
+
FieldSetter<TestClass, int> setter = ReflectionHelpers.GetFieldSetter<
|
|
1942
|
+
TestClass,
|
|
1943
|
+
int
|
|
1944
|
+
>(field);
|
|
1945
|
+
TestClass instance = new();
|
|
1946
|
+
setter(ref instance, 987);
|
|
1947
|
+
Assert.AreEqual(987, instance.intValue);
|
|
1948
|
+
});
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
[Test]
|
|
1952
|
+
public void DynamicIlTypedFieldGetterReturnsValue()
|
|
1953
|
+
{
|
|
1954
|
+
RunWithDynamicIlOnly(() =>
|
|
1955
|
+
{
|
|
1956
|
+
TestClass instance = new() { intValue = 741 };
|
|
1957
|
+
FieldInfo field = typeof(TestClass).GetField(nameof(TestClass.intValue));
|
|
1958
|
+
Func<TestClass, int> getter = ReflectionHelpers.GetFieldGetter<TestClass, int>(
|
|
1959
|
+
field
|
|
1960
|
+
);
|
|
1961
|
+
Assert.AreEqual(741, getter(instance));
|
|
1962
|
+
});
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
[Test]
|
|
1966
|
+
public void DynamicIlTypedStaticFieldSetterMutatesValue()
|
|
1967
|
+
{
|
|
1968
|
+
RunWithDynamicIlOnly(() =>
|
|
1969
|
+
{
|
|
1970
|
+
FieldInfo field = typeof(TestClass).GetField(nameof(TestClass.StaticIntValue));
|
|
1971
|
+
int original = TestClass.StaticIntValue;
|
|
1972
|
+
try
|
|
1973
|
+
{
|
|
1974
|
+
Action<int> setter = ReflectionHelpers.GetStaticFieldSetter<int>(field);
|
|
1975
|
+
setter(512);
|
|
1976
|
+
Assert.AreEqual(512, TestClass.StaticIntValue);
|
|
1977
|
+
}
|
|
1978
|
+
finally
|
|
1979
|
+
{
|
|
1980
|
+
TestClass.StaticIntValue = original;
|
|
1981
|
+
}
|
|
1982
|
+
});
|
|
1983
|
+
}
|
|
1984
|
+
|
|
1985
|
+
[Test]
|
|
1986
|
+
public void DynamicIlTypedPropertySetterMutatesInstance()
|
|
1987
|
+
{
|
|
1988
|
+
RunWithDynamicIlOnly(() =>
|
|
1989
|
+
{
|
|
1990
|
+
PropertyInfo property = typeof(TestPropertyClass).GetProperty(
|
|
1991
|
+
nameof(TestPropertyClass.InstanceProperty)
|
|
1992
|
+
);
|
|
1993
|
+
Action<TestPropertyClass, int> setter = ReflectionHelpers.GetPropertySetter<
|
|
1994
|
+
TestPropertyClass,
|
|
1995
|
+
int
|
|
1996
|
+
>(property);
|
|
1997
|
+
TestPropertyClass instance = new();
|
|
1998
|
+
setter(instance, 222);
|
|
1999
|
+
Assert.AreEqual(222, instance.InstanceProperty);
|
|
2000
|
+
});
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
[Test]
|
|
2004
|
+
public void DynamicIlTypedPropertyGetterReturnsValue()
|
|
2005
|
+
{
|
|
2006
|
+
RunWithDynamicIlOnly(() =>
|
|
2007
|
+
{
|
|
2008
|
+
PropertyInfo property = typeof(TestPropertyClass).GetProperty(
|
|
2009
|
+
nameof(TestPropertyClass.InstanceProperty)
|
|
2010
|
+
);
|
|
2011
|
+
TestPropertyClass instance = new();
|
|
2012
|
+
Func<TestPropertyClass, int> getter = ReflectionHelpers.GetPropertyGetter<
|
|
2013
|
+
TestPropertyClass,
|
|
2014
|
+
int
|
|
2015
|
+
>(property);
|
|
2016
|
+
Assert.AreEqual(instance.InstanceProperty, getter(instance));
|
|
2017
|
+
});
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
[Test]
|
|
2021
|
+
public void DynamicIlTypedStaticPropertySetterMutatesValue()
|
|
2022
|
+
{
|
|
2023
|
+
RunWithDynamicIlOnly(() =>
|
|
2024
|
+
{
|
|
2025
|
+
PropertyInfo property = typeof(TestPropertyClass).GetProperty(
|
|
2026
|
+
nameof(TestPropertyClass.StaticProperty)
|
|
2027
|
+
);
|
|
2028
|
+
int original = TestPropertyClass.StaticProperty;
|
|
2029
|
+
try
|
|
2030
|
+
{
|
|
2031
|
+
Action<int> setter = ReflectionHelpers.GetStaticPropertySetter<int>(property);
|
|
2032
|
+
setter(314);
|
|
2033
|
+
Assert.AreEqual(314, TestPropertyClass.StaticProperty);
|
|
2034
|
+
}
|
|
2035
|
+
finally
|
|
2036
|
+
{
|
|
2037
|
+
TestPropertyClass.StaticProperty = original;
|
|
2038
|
+
}
|
|
2039
|
+
});
|
|
2040
|
+
}
|
|
2041
|
+
|
|
2042
|
+
[Test]
|
|
2043
|
+
public void DynamicIlInstanceMethodInvokerReturnsValue()
|
|
2044
|
+
{
|
|
2045
|
+
RunWithDynamicIlOnly(() =>
|
|
2046
|
+
{
|
|
2047
|
+
MethodInfo method = typeof(TestMethodClass).GetMethod(
|
|
2048
|
+
nameof(TestMethodClass.InstanceMethodWithParam)
|
|
2049
|
+
);
|
|
2050
|
+
Func<object, object[], object> invoker = ReflectionHelpers.GetMethodInvoker(method);
|
|
2051
|
+
TestMethodClass instance = new();
|
|
2052
|
+
object result = invoker(instance, new object[] { "abcd" });
|
|
2053
|
+
Assert.AreEqual(4, result);
|
|
2054
|
+
});
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
[Test]
|
|
2058
|
+
public void DynamicIlTypedInstanceMethodInvokerReturnsValue()
|
|
2059
|
+
{
|
|
2060
|
+
RunWithDynamicIlOnly(() =>
|
|
2061
|
+
{
|
|
2062
|
+
MethodInfo method = typeof(TestMethodClass).GetMethod(
|
|
2063
|
+
nameof(TestMethodClass.InstanceIntMethod)
|
|
2064
|
+
);
|
|
2065
|
+
Func<TestMethodClass, int> invoker = ReflectionHelpers.GetInstanceMethodInvoker<
|
|
2066
|
+
TestMethodClass,
|
|
2067
|
+
int
|
|
2068
|
+
>(method);
|
|
2069
|
+
TestMethodClass instance = new();
|
|
2070
|
+
Assert.AreEqual(100, invoker(instance));
|
|
2071
|
+
});
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2074
|
+
[Test]
|
|
2075
|
+
public void DynamicIlTypedStaticMethodInvokerReturnsValue()
|
|
2076
|
+
{
|
|
2077
|
+
RunWithDynamicIlOnly(() =>
|
|
2078
|
+
{
|
|
2079
|
+
MethodInfo method = typeof(TestMethodClass).GetMethod(
|
|
2080
|
+
nameof(TestMethodClass.StaticIntMethod)
|
|
2081
|
+
);
|
|
2082
|
+
Func<int> invoker = ReflectionHelpers.GetStaticMethodInvoker<int>(method);
|
|
2083
|
+
Assert.AreEqual(42, invoker());
|
|
2084
|
+
});
|
|
2085
|
+
}
|
|
2086
|
+
|
|
2087
|
+
[Test]
|
|
2088
|
+
public void DynamicIlConstructorInvokerCreatesInstance()
|
|
2089
|
+
{
|
|
2090
|
+
RunWithDynamicIlOnly(() =>
|
|
2091
|
+
{
|
|
2092
|
+
ConstructorInfo ctor = typeof(TestConstructorClass).GetConstructor(
|
|
2093
|
+
new[] { typeof(int), typeof(string) }
|
|
2094
|
+
);
|
|
2095
|
+
Func<object[], object> invoker = ReflectionHelpers.GetConstructor(ctor);
|
|
2096
|
+
object created = invoker(new object[] { 5, "five" });
|
|
2097
|
+
Assert.IsInstanceOf<TestConstructorClass>(created);
|
|
2098
|
+
TestConstructorClass instance = (TestConstructorClass)created;
|
|
2099
|
+
Assert.AreEqual(5, instance.Value1);
|
|
2100
|
+
Assert.AreEqual("five", instance.Value2);
|
|
2101
|
+
});
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
[Test]
|
|
2105
|
+
public void DynamicIlParameterlessConstructorCreatesInstance()
|
|
2106
|
+
{
|
|
2107
|
+
RunWithDynamicIlOnly(() =>
|
|
2108
|
+
{
|
|
2109
|
+
Func<TestConstructorClass> ctor =
|
|
2110
|
+
ReflectionHelpers.GetParameterlessConstructor<TestConstructorClass>();
|
|
2111
|
+
TestConstructorClass instance = ctor();
|
|
2112
|
+
Assert.IsNotNull(instance);
|
|
2113
|
+
});
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2116
|
+
[Test]
|
|
2117
|
+
public void DynamicIlIndexerSetterAndGetterRoundTrip()
|
|
2118
|
+
{
|
|
2119
|
+
RunWithDynamicIlOnly(() =>
|
|
2120
|
+
{
|
|
2121
|
+
PropertyInfo indexer = typeof(IndexerClass).GetProperty("Item");
|
|
2122
|
+
Func<object, object[], object> getter = ReflectionHelpers.GetIndexerGetter(indexer);
|
|
2123
|
+
Action<object, object, object[]> setter = ReflectionHelpers.GetIndexerSetter(
|
|
2124
|
+
indexer
|
|
2125
|
+
);
|
|
2126
|
+
IndexerClass instance = new();
|
|
2127
|
+
setter(instance, 13, new object[] { 2 });
|
|
2128
|
+
Assert.AreEqual(13, getter(instance, new object[] { 2 }));
|
|
2129
|
+
});
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
private static void RunWithDynamicIlOnly(Action assertion)
|
|
2133
|
+
{
|
|
2134
|
+
if (!ReflectionHelpers.DynamicIlEnabled)
|
|
2135
|
+
{
|
|
2136
|
+
Assert.Ignore("Dynamic IL is not available on this platform.");
|
|
2137
|
+
}
|
|
2138
|
+
|
|
2139
|
+
using (
|
|
2140
|
+
ReflectionHelpers.OverrideReflectionCapabilities(
|
|
2141
|
+
expressions: false,
|
|
2142
|
+
dynamicIl: true
|
|
2143
|
+
)
|
|
2144
|
+
)
|
|
2145
|
+
{
|
|
2146
|
+
assertion();
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
|
|
2150
|
+
[Test]
|
|
2151
|
+
public void TypedPropertySetterCastsReferenceTypes()
|
|
2152
|
+
{
|
|
2153
|
+
VariantPropertyClass instance = new();
|
|
2154
|
+
PropertyInfo property = typeof(VariantPropertyClass).GetProperty(
|
|
2155
|
+
nameof(VariantPropertyClass.ObjectProperty)
|
|
2156
|
+
);
|
|
2157
|
+
Action<VariantPropertyClass, string> setter = ReflectionHelpers.GetPropertySetter<
|
|
2158
|
+
VariantPropertyClass,
|
|
2159
|
+
string
|
|
2160
|
+
>(property);
|
|
2161
|
+
setter(instance, "updated");
|
|
2162
|
+
Assert.AreEqual("updated", instance.ObjectProperty);
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2165
|
+
[Test]
|
|
2166
|
+
public void TypedStaticPropertySetterCastsReferenceTypes()
|
|
2167
|
+
{
|
|
2168
|
+
PropertyInfo property = typeof(VariantPropertyClass).GetProperty(
|
|
2169
|
+
nameof(VariantPropertyClass.StaticObjectProperty)
|
|
2170
|
+
);
|
|
2171
|
+
object original = VariantPropertyClass.StaticObjectProperty;
|
|
2172
|
+
try
|
|
2173
|
+
{
|
|
2174
|
+
Action<string> setter = ReflectionHelpers.GetStaticPropertySetter<string>(property);
|
|
2175
|
+
setter("world");
|
|
2176
|
+
Func<string> getter = ReflectionHelpers.GetStaticPropertyGetter<string>(property);
|
|
2177
|
+
Assert.AreEqual("world", getter());
|
|
2178
|
+
}
|
|
2179
|
+
finally
|
|
2180
|
+
{
|
|
2181
|
+
VariantPropertyClass.StaticObjectProperty = original;
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
[Test]
|
|
2186
|
+
public void ParameterlessConstructorDelegateCreatesInstances()
|
|
2187
|
+
{
|
|
2188
|
+
Func<object> creator = ReflectionHelpers.GetParameterlessConstructor(
|
|
2189
|
+
typeof(TestConstructorClass)
|
|
2190
|
+
);
|
|
2191
|
+
object first = creator();
|
|
2192
|
+
object second = creator();
|
|
2193
|
+
Assert.IsInstanceOf<TestConstructorClass>(first);
|
|
2194
|
+
Assert.IsInstanceOf<TestConstructorClass>(second);
|
|
2195
|
+
Assert.AreNotSame(first, second);
|
|
2196
|
+
}
|
|
2197
|
+
|
|
2198
|
+
[Test]
|
|
2199
|
+
public void ParameterlessConstructorFallbackUsesReflectionWhenExpressionsDisabled()
|
|
2200
|
+
{
|
|
2201
|
+
using (
|
|
2202
|
+
ReflectionHelpers.OverrideReflectionCapabilities(
|
|
2203
|
+
expressions: false,
|
|
2204
|
+
dynamicIl: false
|
|
2205
|
+
)
|
|
2206
|
+
)
|
|
2207
|
+
{
|
|
2208
|
+
Func<TestConstructorClass> creator =
|
|
2209
|
+
ReflectionHelpers.GetParameterlessConstructor<TestConstructorClass>();
|
|
2210
|
+
TestConstructorClass instance = creator();
|
|
2211
|
+
Assert.IsNotNull(instance);
|
|
2212
|
+
Assert.AreEqual(0, instance.Value1);
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2216
|
+
[Test]
|
|
2217
|
+
public void ConstructorInvokerCreatesTypedInstance()
|
|
2218
|
+
{
|
|
2219
|
+
ConstructorInfo ctor = typeof(GenericTestClass<int>).GetConstructor(
|
|
2220
|
+
new[] { typeof(int) }
|
|
2221
|
+
);
|
|
2222
|
+
Func<object[], object> invoker = ReflectionHelpers.GetConstructor(ctor);
|
|
2223
|
+
object result = invoker(new object[] { 256 });
|
|
2224
|
+
Assert.IsInstanceOf<GenericTestClass<int>>(result);
|
|
2225
|
+
Assert.AreEqual(256, ((GenericTestClass<int>)result).Value);
|
|
2226
|
+
}
|
|
2227
|
+
|
|
2228
|
+
[Test]
|
|
2229
|
+
public void ConstructorInvokerFallsBackWhenExpressionsDisabled()
|
|
2230
|
+
{
|
|
2231
|
+
ConstructorInfo ctor = typeof(GenericTestClass<int>).GetConstructor(
|
|
2232
|
+
new[] { typeof(int) }
|
|
2233
|
+
);
|
|
2234
|
+
using (
|
|
2235
|
+
ReflectionHelpers.OverrideReflectionCapabilities(
|
|
2236
|
+
expressions: false,
|
|
2237
|
+
dynamicIl: false
|
|
2238
|
+
)
|
|
2239
|
+
)
|
|
2240
|
+
{
|
|
2241
|
+
Func<object[], object> invoker = ReflectionHelpers.GetConstructor(ctor);
|
|
2242
|
+
object result = invoker(new object[] { 64 });
|
|
2243
|
+
Assert.IsInstanceOf<GenericTestClass<int>>(result);
|
|
2244
|
+
Assert.AreEqual(64, ((GenericTestClass<int>)result).Value);
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
|
|
2248
|
+
[Test]
|
|
2249
|
+
public void IndexerGetterThrowsOnInvalidIndexCount()
|
|
2250
|
+
{
|
|
2251
|
+
PropertyInfo idxProp = typeof(IndexerClass).GetProperty("Item");
|
|
2252
|
+
Func<object, object[], object> getter = ReflectionHelpers.GetIndexerGetter(idxProp);
|
|
2253
|
+
IndexerClass obj = new();
|
|
2254
|
+
Assert.Throws<IndexOutOfRangeException>(() => getter(obj, Array.Empty<object>()));
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
[Test]
|
|
2258
|
+
public void IndexerHelpersFallbackWhenExpressionsDisabled()
|
|
2259
|
+
{
|
|
2260
|
+
PropertyInfo idxProp = typeof(IndexerClass).GetProperty("Item");
|
|
2261
|
+
using (
|
|
2262
|
+
ReflectionHelpers.OverrideReflectionCapabilities(
|
|
2263
|
+
expressions: false,
|
|
2264
|
+
dynamicIl: false
|
|
2265
|
+
)
|
|
2266
|
+
)
|
|
2267
|
+
{
|
|
2268
|
+
Func<object, object[], object> getter = ReflectionHelpers.GetIndexerGetter(idxProp);
|
|
2269
|
+
Action<object, object, object[]> setter = ReflectionHelpers.GetIndexerSetter(
|
|
2270
|
+
idxProp
|
|
2271
|
+
);
|
|
2272
|
+
IndexerClass obj = new();
|
|
2273
|
+
setter(obj, 99, new object[] { 3 });
|
|
2274
|
+
Assert.AreEqual(99, getter(obj, new object[] { 3 }));
|
|
2275
|
+
}
|
|
2276
|
+
}
|
|
2277
|
+
|
|
2278
|
+
[Test]
|
|
2279
|
+
public void TypedFieldGetterBoxesValueTypeWhenRequested()
|
|
2280
|
+
{
|
|
2281
|
+
FieldInfo field = typeof(TestClass).GetField(nameof(TestClass.intValue));
|
|
2282
|
+
Func<TestClass, object> getter = ReflectionHelpers.GetFieldGetter<TestClass, object>(
|
|
2283
|
+
field
|
|
2284
|
+
);
|
|
2285
|
+
TestClass instance = new() { intValue = 512 };
|
|
2286
|
+
Assert.AreEqual(512, getter(instance));
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2289
|
+
[Test]
|
|
2290
|
+
public void TypedFieldSetterUnboxesValueTypes()
|
|
2291
|
+
{
|
|
2292
|
+
FieldInfo field = typeof(TestClass).GetField(nameof(TestClass.intValue));
|
|
2293
|
+
FieldSetter<TestClass, object> setter = ReflectionHelpers.GetFieldSetter<
|
|
2294
|
+
TestClass,
|
|
2295
|
+
object
|
|
2296
|
+
>(field);
|
|
2297
|
+
TestClass instance = new();
|
|
2298
|
+
setter(ref instance, 2048);
|
|
2299
|
+
Assert.AreEqual(2048, instance.intValue);
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
[Test]
|
|
2303
|
+
public void TypedStaticFieldSetterUnboxesValueTypes()
|
|
2304
|
+
{
|
|
2305
|
+
FieldInfo field = typeof(TestClass).GetField(
|
|
2306
|
+
nameof(TestClass.StaticIntValue),
|
|
2307
|
+
BindingFlags.Static | BindingFlags.Public
|
|
2308
|
+
);
|
|
2309
|
+
int original = TestClass.StaticIntValue;
|
|
2310
|
+
try
|
|
2311
|
+
{
|
|
2312
|
+
Action<object> setter = ReflectionHelpers.GetStaticFieldSetter<object>(field);
|
|
2313
|
+
setter(1024);
|
|
2314
|
+
Assert.AreEqual(1024, TestClass.StaticIntValue);
|
|
2315
|
+
}
|
|
2316
|
+
finally
|
|
2317
|
+
{
|
|
2318
|
+
TestClass.StaticIntValue = original;
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
[Test]
|
|
2323
|
+
public void TypedFieldGetterCastsReferenceTypes()
|
|
2324
|
+
{
|
|
2325
|
+
VariantPropertyClass instance = new() { ObjectField = "hello" };
|
|
2326
|
+
FieldInfo field = typeof(VariantPropertyClass).GetField(
|
|
2327
|
+
nameof(VariantPropertyClass.ObjectField)
|
|
2328
|
+
);
|
|
2329
|
+
Func<VariantPropertyClass, string> getter = ReflectionHelpers.GetFieldGetter<
|
|
2330
|
+
VariantPropertyClass,
|
|
2331
|
+
string
|
|
2332
|
+
>(field);
|
|
2333
|
+
Assert.AreEqual("hello", getter(instance));
|
|
2334
|
+
}
|
|
2335
|
+
|
|
2336
|
+
[Test]
|
|
2337
|
+
public void TypedFieldSetterFallbacksWhenCapabilitiesDisabled()
|
|
2338
|
+
{
|
|
2339
|
+
FieldInfo field = typeof(TestClass).GetField(nameof(TestClass.intValue));
|
|
2340
|
+
using (
|
|
2341
|
+
ReflectionHelpers.OverrideReflectionCapabilities(
|
|
2342
|
+
expressions: false,
|
|
2343
|
+
dynamicIl: false
|
|
2344
|
+
)
|
|
2345
|
+
)
|
|
2346
|
+
{
|
|
2347
|
+
FieldSetter<TestClass, int> setter = ReflectionHelpers.GetFieldSetter<
|
|
2348
|
+
TestClass,
|
|
2349
|
+
int
|
|
2350
|
+
>(field);
|
|
2351
|
+
TestClass instance = new();
|
|
2352
|
+
setter(ref instance, 321);
|
|
2353
|
+
Assert.AreEqual(321, instance.intValue);
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
|
|
2357
|
+
[Test]
|
|
2358
|
+
public void TypedPropertySetterFallbacksWhenCapabilitiesDisabled()
|
|
2359
|
+
{
|
|
2360
|
+
PropertyInfo property = typeof(GenericTestClass<int>).GetProperty(
|
|
2361
|
+
nameof(GenericTestClass<int>.Value)
|
|
2362
|
+
);
|
|
2363
|
+
using (
|
|
2364
|
+
ReflectionHelpers.OverrideReflectionCapabilities(
|
|
2365
|
+
expressions: false,
|
|
2366
|
+
dynamicIl: false
|
|
2367
|
+
)
|
|
2368
|
+
)
|
|
2369
|
+
{
|
|
2370
|
+
Action<GenericTestClass<int>, int> setter = ReflectionHelpers.GetPropertySetter<
|
|
2371
|
+
GenericTestClass<int>,
|
|
2372
|
+
int
|
|
2373
|
+
>(property);
|
|
2374
|
+
GenericTestClass<int> instance = new();
|
|
2375
|
+
setter(instance, 87);
|
|
2376
|
+
Assert.AreEqual(87, instance.Value);
|
|
2377
|
+
}
|
|
2378
|
+
}
|
|
2379
|
+
|
|
2380
|
+
[Test]
|
|
2381
|
+
public void TypedPropertyGetterFallbacksWhenCapabilitiesDisabled()
|
|
2382
|
+
{
|
|
2383
|
+
PropertyInfo property = typeof(GenericTestClass<int>).GetProperty(
|
|
2384
|
+
nameof(GenericTestClass<int>.Value)
|
|
2385
|
+
);
|
|
2386
|
+
GenericTestClass<int> instance = new(45);
|
|
2387
|
+
using (
|
|
2388
|
+
ReflectionHelpers.OverrideReflectionCapabilities(
|
|
2389
|
+
expressions: false,
|
|
2390
|
+
dynamicIl: false
|
|
2391
|
+
)
|
|
2392
|
+
)
|
|
2393
|
+
{
|
|
2394
|
+
Func<GenericTestClass<int>, int> getter = ReflectionHelpers.GetPropertyGetter<
|
|
2395
|
+
GenericTestClass<int>,
|
|
2396
|
+
int
|
|
2397
|
+
>(property);
|
|
2398
|
+
Assert.AreEqual(45, getter(instance));
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
|
|
2402
|
+
[Test]
|
|
2403
|
+
public void TypedFieldSetterCastsReferenceTypes()
|
|
2404
|
+
{
|
|
2405
|
+
VariantPropertyClass instance = new();
|
|
2406
|
+
FieldInfo field = typeof(VariantPropertyClass).GetField(
|
|
2407
|
+
nameof(VariantPropertyClass.ObjectField)
|
|
2408
|
+
);
|
|
2409
|
+
FieldSetter<VariantPropertyClass, string> setter = ReflectionHelpers.GetFieldSetter<
|
|
2410
|
+
VariantPropertyClass,
|
|
2411
|
+
string
|
|
2412
|
+
>(field);
|
|
2413
|
+
setter(ref instance, "updated");
|
|
2414
|
+
Assert.AreEqual("updated", instance.ObjectField);
|
|
2415
|
+
}
|
|
2416
|
+
|
|
2417
|
+
[Test]
|
|
2418
|
+
public void TypedStaticFieldSetterCastsReferenceTypes()
|
|
2419
|
+
{
|
|
2420
|
+
FieldInfo field = typeof(VariantPropertyClass).GetField(
|
|
2421
|
+
nameof(VariantPropertyClass.StaticObjectField),
|
|
2422
|
+
BindingFlags.Static | BindingFlags.Public
|
|
2423
|
+
);
|
|
2424
|
+
object original = VariantPropertyClass.StaticObjectField;
|
|
2425
|
+
try
|
|
2426
|
+
{
|
|
2427
|
+
Action<string> setter = ReflectionHelpers.GetStaticFieldSetter<string>(field);
|
|
2428
|
+
setter("world");
|
|
2429
|
+
Func<string> getter = ReflectionHelpers.GetStaticFieldGetter<string>(field);
|
|
2430
|
+
Assert.AreEqual("world", getter());
|
|
2431
|
+
}
|
|
2432
|
+
finally
|
|
2433
|
+
{
|
|
2434
|
+
VariantPropertyClass.StaticObjectField = original;
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
|
|
2438
|
+
[Test]
|
|
2439
|
+
public void TypedFieldGetterSupportsFallbackWhenInstanceTypeDiffers()
|
|
2440
|
+
{
|
|
2441
|
+
FieldInfo field = typeof(TestClass).GetField(nameof(TestClass.intValue));
|
|
2442
|
+
Func<object, int> getter = ReflectionHelpers.GetFieldGetter<object, int>(field);
|
|
2443
|
+
TestClass instance = new() { intValue = 77 };
|
|
2444
|
+
object boxed = instance;
|
|
2445
|
+
Assert.AreEqual(77, getter(boxed));
|
|
2446
|
+
}
|
|
2447
|
+
|
|
2448
|
+
[Test]
|
|
2449
|
+
public void TypedFieldSetterSupportsFallbackWhenInstanceTypeDiffers()
|
|
2450
|
+
{
|
|
2451
|
+
FieldInfo field = typeof(TestClass).GetField(nameof(TestClass.intValue));
|
|
2452
|
+
FieldSetter<object, int> setter = ReflectionHelpers.GetFieldSetter<object, int>(field);
|
|
2453
|
+
object boxed = new TestClass();
|
|
2454
|
+
setter(ref boxed, 88);
|
|
2455
|
+
Assert.AreEqual(88, ((TestClass)boxed).intValue);
|
|
2456
|
+
}
|
|
2457
|
+
|
|
1798
2458
|
[Test]
|
|
1799
2459
|
public void TypedStaticInvokerWrongReturnTypeThrows()
|
|
1800
2460
|
{
|