com.wallstop-studios.unity-helpers 2.0.0-rc79.5 → 2.0.0-rc79.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,10 +3,28 @@ namespace WallstopStudios.UnityHelpers.Tests.Helper
3
3
  using System;
4
4
  using System.Collections;
5
5
  using System.Collections.Generic;
6
+ using System.Linq;
6
7
  using System.Reflection;
7
8
  using NUnit.Framework;
8
9
  using WallstopStudios.UnityHelpers.Core.Helper;
9
10
  using WallstopStudios.UnityHelpers.Core.Random;
11
+ using CategoryAttribute = System.ComponentModel.CategoryAttribute;
12
+ using DescriptionAttribute = System.ComponentModel.DescriptionAttribute;
13
+
14
+ [AttributeUsage(AttributeTargets.All)]
15
+ public class ReflectionTestAttribute : Attribute
16
+ {
17
+ public string Name { get; set; }
18
+ public int Value { get; set; }
19
+
20
+ public ReflectionTestAttribute() { }
21
+
22
+ public ReflectionTestAttribute(string name, int value)
23
+ {
24
+ Name = name;
25
+ Value = value;
26
+ }
27
+ }
10
28
 
11
29
  public struct TestStruct
12
30
  {
@@ -20,6 +38,202 @@ namespace WallstopStudios.UnityHelpers.Tests.Helper
20
38
  public int intValue;
21
39
  }
22
40
 
41
+ public class TestMethodClass
42
+ {
43
+ public static int StaticMethodCallCount = 0;
44
+ public int InstanceMethodCallCount = 0;
45
+
46
+ // Void methods
47
+ public static void StaticVoidMethod()
48
+ {
49
+ StaticMethodCallCount++;
50
+ }
51
+
52
+ public void InstanceVoidMethod()
53
+ {
54
+ InstanceMethodCallCount++;
55
+ }
56
+
57
+ // Return value methods
58
+ public static int StaticIntMethod()
59
+ {
60
+ StaticMethodCallCount++;
61
+ return 42;
62
+ }
63
+
64
+ public static string StaticStringMethod()
65
+ {
66
+ StaticMethodCallCount++;
67
+ return "test";
68
+ }
69
+
70
+ public static bool StaticBoolMethod()
71
+ {
72
+ StaticMethodCallCount++;
73
+ return true;
74
+ }
75
+
76
+ public int InstanceIntMethod()
77
+ {
78
+ InstanceMethodCallCount++;
79
+ return 100;
80
+ }
81
+
82
+ public string InstanceStringMethod()
83
+ {
84
+ InstanceMethodCallCount++;
85
+ return "instance";
86
+ }
87
+
88
+ // Methods with parameters
89
+ public static int StaticMethodWithParam(int param)
90
+ {
91
+ StaticMethodCallCount++;
92
+ return param * 2;
93
+ }
94
+
95
+ public int InstanceMethodWithParam(string param)
96
+ {
97
+ InstanceMethodCallCount++;
98
+ return param?.Length ?? 0;
99
+ }
100
+
101
+ public static void StaticVoidMethodWithParam(int param)
102
+ {
103
+ StaticMethodCallCount = param;
104
+ }
105
+
106
+ // Multiple parameter methods
107
+ public static int StaticMethodMultipleParams(int a, string b, bool c)
108
+ {
109
+ StaticMethodCallCount++;
110
+ return a + (b?.Length ?? 0) + (c ? 1 : 0);
111
+ }
112
+
113
+ public void Reset()
114
+ {
115
+ StaticMethodCallCount = 0;
116
+ InstanceMethodCallCount = 0;
117
+ }
118
+ }
119
+
120
+ public sealed class TestConstructorClass
121
+ {
122
+ public int Value1 { get; }
123
+ public string Value2 { get; }
124
+ public bool Value3 { get; }
125
+
126
+ public TestConstructorClass()
127
+ {
128
+ Value1 = 0;
129
+ Value2 = "default";
130
+ Value3 = false;
131
+ }
132
+
133
+ public TestConstructorClass(int value1)
134
+ {
135
+ Value1 = value1;
136
+ Value2 = "single";
137
+ Value3 = false;
138
+ }
139
+
140
+ public TestConstructorClass(int value1, string value2)
141
+ {
142
+ Value1 = value1;
143
+ Value2 = value2;
144
+ Value3 = false;
145
+ }
146
+
147
+ public TestConstructorClass(int value1, string value2, bool value3)
148
+ {
149
+ Value1 = value1;
150
+ Value2 = value2;
151
+ Value3 = value3;
152
+ }
153
+ }
154
+
155
+ public readonly struct TestConstructorStruct
156
+ {
157
+ public int Value { get; }
158
+
159
+ public TestConstructorStruct(int value)
160
+ {
161
+ Value = value;
162
+ }
163
+ }
164
+
165
+ public sealed class TestPropertyClass
166
+ {
167
+ private static int _staticValue = 50;
168
+ private int _instanceValue = 25;
169
+
170
+ public static int StaticProperty
171
+ {
172
+ get => _staticValue;
173
+ set => _staticValue = value;
174
+ }
175
+
176
+ public int InstanceProperty
177
+ {
178
+ get => _instanceValue;
179
+ set => _instanceValue = value;
180
+ }
181
+
182
+ public static string StaticStringProperty { get; set; } = "static";
183
+
184
+ public string InstanceStringProperty { get; set; } = "instance";
185
+
186
+ // Read-only properties
187
+ public static int StaticReadOnlyProperty => 999;
188
+ public int InstanceReadOnlyProperty => 888;
189
+ }
190
+
191
+ [Description("Test class for attribute testing")]
192
+ [ReflectionTestAttribute("ClassLevel", 10)]
193
+ public sealed class TestAttributeClass
194
+ {
195
+ [Description("Static field with description")]
196
+ [ReflectionTestAttribute("StaticField", 15)]
197
+ public static int StaticFieldWithAttribute = 1;
198
+
199
+ [Category("TestCategory")]
200
+ [ReflectionTestAttribute("InstanceField", 5)]
201
+ public int InstanceFieldWithAttribute = 2;
202
+
203
+ [Description("Static property for testing")]
204
+ [ReflectionTestAttribute("StaticProperty", 20)]
205
+ public static string StaticPropertyWithAttribute { get; set; } = "static";
206
+
207
+ [Category("TestCategory")]
208
+ [Description("Instance property")]
209
+ [ReflectionTestAttribute("InstanceProperty", 8)]
210
+ public string InstancePropertyWithAttribute { get; set; } = "instance";
211
+
212
+ [Description("Static method for testing")]
213
+ [ReflectionTestAttribute("StaticMethod", 12)]
214
+ public static void StaticMethodWithAttribute() { }
215
+
216
+ [Category("TestCategory")]
217
+ [ReflectionTestAttribute("InstanceMethod", 7)]
218
+ public void InstanceMethodWithAttribute() { }
219
+
220
+ public void MethodWithAttributedParameter(
221
+ [Description("Parameter with description")] int param
222
+ ) { }
223
+ }
224
+
225
+ public sealed class GenericTestClass<T>
226
+ {
227
+ public T Value { get; set; }
228
+
229
+ public GenericTestClass() { }
230
+
231
+ public GenericTestClass(T value)
232
+ {
233
+ Value = value;
234
+ }
235
+ }
236
+
23
237
  public sealed class ReflectionHelperTests
24
238
  {
25
239
  private const int NumTries = 1_000;
@@ -528,5 +742,752 @@ namespace WallstopStudios.UnityHelpers.Tests.Helper
528
742
  }
529
743
  }
530
744
  }
745
+
746
+ [Test]
747
+ public void GetArrayCreator()
748
+ {
749
+ Func<int, Array> arrayCreator = ReflectionHelpers.GetArrayCreator(typeof(int));
750
+ Assert.IsNotNull(arrayCreator);
751
+
752
+ for (int i = 0; i < 10; ++i)
753
+ {
754
+ int size = PRNG.Instance.Next(1, 100);
755
+ Array created = arrayCreator(size);
756
+ Assert.IsNotNull(created);
757
+ Assert.AreEqual(size, created.Length);
758
+ Assert.IsTrue(created is int[]);
759
+ }
760
+ }
761
+
762
+ [Test]
763
+ public void GetListCreator()
764
+ {
765
+ Func<IList> listCreator = ReflectionHelpers.GetListCreator(typeof(string));
766
+ Assert.IsNotNull(listCreator);
767
+
768
+ for (int i = 0; i < 10; ++i)
769
+ {
770
+ IList created = listCreator();
771
+ Assert.IsNotNull(created);
772
+ Assert.AreEqual(0, created.Count);
773
+ Assert.IsTrue(created is List<string>);
774
+ }
775
+ }
776
+
777
+ [Test]
778
+ public void GetListWithCapacityCreator()
779
+ {
780
+ Func<int, IList> listCreator = ReflectionHelpers.GetListWithCapacityCreator(
781
+ typeof(bool)
782
+ );
783
+ Assert.IsNotNull(listCreator);
784
+
785
+ for (int i = 0; i < 10; ++i)
786
+ {
787
+ int capacity = PRNG.Instance.Next(1, 100);
788
+ IList created = listCreator(capacity);
789
+ Assert.IsNotNull(created);
790
+ Assert.AreEqual(0, created.Count);
791
+ Assert.IsTrue(created is List<bool>);
792
+ Assert.AreEqual(capacity, ((List<bool>)created).Capacity);
793
+ }
794
+ }
795
+
796
+ [Test]
797
+ public void InvokeStaticVoidMethod()
798
+ {
799
+ TestMethodClass testObj = new();
800
+ testObj.Reset();
801
+
802
+ MethodInfo method = typeof(TestMethodClass).GetMethod(
803
+ nameof(TestMethodClass.StaticVoidMethod)
804
+ );
805
+ Assert.IsNotNull(method);
806
+
807
+ int initialCount = TestMethodClass.StaticMethodCallCount;
808
+ object result = ReflectionHelpers.InvokeStaticMethod(method);
809
+
810
+ Assert.IsNull(result);
811
+ Assert.AreEqual(initialCount + 1, TestMethodClass.StaticMethodCallCount);
812
+ }
813
+
814
+ [Test]
815
+ public void InvokeStaticMethodWithReturnValue()
816
+ {
817
+ TestMethodClass testObj = new();
818
+ testObj.Reset();
819
+
820
+ MethodInfo intMethod = typeof(TestMethodClass).GetMethod(
821
+ nameof(TestMethodClass.StaticIntMethod)
822
+ );
823
+ MethodInfo stringMethod = typeof(TestMethodClass).GetMethod(
824
+ nameof(TestMethodClass.StaticStringMethod)
825
+ );
826
+ MethodInfo boolMethod = typeof(TestMethodClass).GetMethod(
827
+ nameof(TestMethodClass.StaticBoolMethod)
828
+ );
829
+
830
+ Assert.AreEqual(42, ReflectionHelpers.InvokeStaticMethod(intMethod));
831
+ Assert.AreEqual("test", ReflectionHelpers.InvokeStaticMethod(stringMethod));
832
+ Assert.AreEqual(true, ReflectionHelpers.InvokeStaticMethod(boolMethod));
833
+ Assert.AreEqual(3, TestMethodClass.StaticMethodCallCount);
834
+ }
835
+
836
+ [Test]
837
+ public void InvokeStaticMethodWithParameters()
838
+ {
839
+ var directResult = TestMethodClass.StaticMethodWithParam(10);
840
+ Assert.AreEqual(20, directResult);
841
+
842
+ TestMethodClass testObj = new();
843
+ testObj.Reset();
844
+
845
+ MethodInfo paramMethod = typeof(TestMethodClass).GetMethod(
846
+ nameof(TestMethodClass.StaticMethodWithParam)
847
+ );
848
+ MethodInfo voidParamMethod = typeof(TestMethodClass).GetMethod(
849
+ nameof(TestMethodClass.StaticVoidMethodWithParam)
850
+ );
851
+ MethodInfo multiParamMethod = typeof(TestMethodClass).GetMethod(
852
+ nameof(TestMethodClass.StaticMethodMultipleParams)
853
+ );
854
+
855
+ var result1 = ReflectionHelpers.InvokeStaticMethod(paramMethod, 10);
856
+ Assert.AreEqual(20, result1);
857
+ ReflectionHelpers.InvokeStaticMethod(voidParamMethod, 99);
858
+ Assert.AreEqual(99, TestMethodClass.StaticMethodCallCount);
859
+ var result3 = ReflectionHelpers.InvokeStaticMethod(multiParamMethod, 5, "abc", true);
860
+ Assert.AreEqual(9, result3);
861
+ }
862
+
863
+ [Test]
864
+ public void InvokeInstanceMethod()
865
+ {
866
+ TestMethodClass testObj = new();
867
+ testObj.Reset();
868
+
869
+ MethodInfo voidMethod = typeof(TestMethodClass).GetMethod(
870
+ nameof(TestMethodClass.InstanceVoidMethod)
871
+ );
872
+ MethodInfo intMethod = typeof(TestMethodClass).GetMethod(
873
+ nameof(TestMethodClass.InstanceIntMethod)
874
+ );
875
+ MethodInfo stringMethod = typeof(TestMethodClass).GetMethod(
876
+ nameof(TestMethodClass.InstanceStringMethod)
877
+ );
878
+ MethodInfo paramMethod = typeof(TestMethodClass).GetMethod(
879
+ nameof(TestMethodClass.InstanceMethodWithParam)
880
+ );
881
+
882
+ Assert.IsNull(ReflectionHelpers.InvokeMethod(voidMethod, testObj));
883
+ Assert.AreEqual(1, testObj.InstanceMethodCallCount);
884
+
885
+ Assert.AreEqual(100, ReflectionHelpers.InvokeMethod(intMethod, testObj));
886
+ Assert.AreEqual("instance", ReflectionHelpers.InvokeMethod(stringMethod, testObj));
887
+ Assert.AreEqual(5, ReflectionHelpers.InvokeMethod(paramMethod, testObj, "hello"));
888
+ Assert.AreEqual(4, testObj.InstanceMethodCallCount);
889
+ }
890
+
891
+ [Test]
892
+ public void GetMethodInvoker()
893
+ {
894
+ TestMethodClass testObj = new();
895
+ testObj.Reset();
896
+
897
+ MethodInfo voidMethod = typeof(TestMethodClass).GetMethod(
898
+ nameof(TestMethodClass.InstanceVoidMethod)
899
+ );
900
+ MethodInfo intMethod = typeof(TestMethodClass).GetMethod(
901
+ nameof(TestMethodClass.InstanceIntMethod)
902
+ );
903
+ MethodInfo paramMethod = typeof(TestMethodClass).GetMethod(
904
+ nameof(TestMethodClass.InstanceMethodWithParam)
905
+ );
906
+
907
+ Func<object, object[], object> voidInvoker = ReflectionHelpers.GetMethodInvoker(
908
+ voidMethod
909
+ );
910
+ Func<object, object[], object> intInvoker = ReflectionHelpers.GetMethodInvoker(
911
+ intMethod
912
+ );
913
+ Func<object, object[], object> paramInvoker = ReflectionHelpers.GetMethodInvoker(
914
+ paramMethod
915
+ );
916
+
917
+ Assert.IsNull(voidInvoker(testObj, Array.Empty<object>()));
918
+ Assert.AreEqual(1, testObj.InstanceMethodCallCount);
919
+
920
+ Assert.AreEqual(100, intInvoker(testObj, Array.Empty<object>()));
921
+ Assert.AreEqual(2, testObj.InstanceMethodCallCount);
922
+
923
+ Assert.AreEqual(5, paramInvoker(testObj, new object[] { "hello" }));
924
+ Assert.AreEqual(3, testObj.InstanceMethodCallCount);
925
+ }
926
+
927
+ [Test]
928
+ public void GetStaticMethodInvoker()
929
+ {
930
+ TestMethodClass testObj = new();
931
+ testObj.Reset();
932
+
933
+ MethodInfo voidMethod = typeof(TestMethodClass).GetMethod(
934
+ nameof(TestMethodClass.StaticVoidMethod)
935
+ );
936
+ MethodInfo intMethod = typeof(TestMethodClass).GetMethod(
937
+ nameof(TestMethodClass.StaticIntMethod)
938
+ );
939
+ MethodInfo paramMethod = typeof(TestMethodClass).GetMethod(
940
+ nameof(TestMethodClass.StaticMethodWithParam)
941
+ );
942
+
943
+ Func<object[], object> voidInvoker = ReflectionHelpers.GetStaticMethodInvoker(
944
+ voidMethod
945
+ );
946
+ Func<object[], object> intInvoker = ReflectionHelpers.GetStaticMethodInvoker(intMethod);
947
+ Func<object[], object> paramInvoker = ReflectionHelpers.GetStaticMethodInvoker(
948
+ paramMethod
949
+ );
950
+
951
+ Assert.IsNull(voidInvoker(Array.Empty<object>()));
952
+ Assert.AreEqual(1, TestMethodClass.StaticMethodCallCount);
953
+
954
+ Assert.AreEqual(42, intInvoker(Array.Empty<object>()));
955
+ Assert.AreEqual(2, TestMethodClass.StaticMethodCallCount);
956
+
957
+ Assert.AreEqual(20, paramInvoker(new object[] { 10 }));
958
+ Assert.AreEqual(3, TestMethodClass.StaticMethodCallCount);
959
+ }
960
+
961
+ [Test]
962
+ public void CreateInstanceParameterless()
963
+ {
964
+ TestConstructorClass defaultInstance =
965
+ ReflectionHelpers.CreateInstance<TestConstructorClass>();
966
+ Assert.IsNotNull(defaultInstance);
967
+ Assert.AreEqual(0, defaultInstance.Value1);
968
+ Assert.AreEqual("default", defaultInstance.Value2);
969
+ Assert.AreEqual(false, defaultInstance.Value3);
970
+ }
971
+
972
+ [Test]
973
+ public void CreateInstanceWithParameters()
974
+ {
975
+ TestConstructorClass singleParam =
976
+ ReflectionHelpers.CreateInstance<TestConstructorClass>(42);
977
+ Assert.IsNotNull(singleParam);
978
+ Assert.AreEqual(42, singleParam.Value1);
979
+ Assert.AreEqual("single", singleParam.Value2);
980
+ Assert.AreEqual(false, singleParam.Value3);
981
+
982
+ TestConstructorClass twoParam = ReflectionHelpers.CreateInstance<TestConstructorClass>(
983
+ 10,
984
+ "test"
985
+ );
986
+ Assert.IsNotNull(twoParam);
987
+ Assert.AreEqual(10, twoParam.Value1);
988
+ Assert.AreEqual("test", twoParam.Value2);
989
+ Assert.AreEqual(false, twoParam.Value3);
990
+
991
+ TestConstructorClass threeParam =
992
+ ReflectionHelpers.CreateInstance<TestConstructorClass>(5, "hello", true);
993
+ Assert.IsNotNull(threeParam);
994
+ Assert.AreEqual(5, threeParam.Value1);
995
+ Assert.AreEqual("hello", threeParam.Value2);
996
+ Assert.AreEqual(true, threeParam.Value3);
997
+ }
998
+
999
+ [Test]
1000
+ public void CreateInstanceUsingConstructorInfo()
1001
+ {
1002
+ ConstructorInfo[] constructors = typeof(TestConstructorClass).GetConstructors();
1003
+ ConstructorInfo parameterlessConstructor = constructors.First(c =>
1004
+ c.GetParameters().Length == 0
1005
+ );
1006
+ ConstructorInfo singleParamConstructor = constructors.First(c =>
1007
+ c.GetParameters().Length == 1
1008
+ );
1009
+
1010
+ Func<object[], object> parameterlessDelegate = ReflectionHelpers.GetConstructor(
1011
+ parameterlessConstructor
1012
+ );
1013
+ Func<object[], object> singleParamDelegate = ReflectionHelpers.GetConstructor(
1014
+ singleParamConstructor
1015
+ );
1016
+
1017
+ TestConstructorClass instance1 = (TestConstructorClass)parameterlessDelegate(
1018
+ Array.Empty<object>()
1019
+ );
1020
+ Assert.AreEqual(0, instance1.Value1);
1021
+ Assert.AreEqual("default", instance1.Value2);
1022
+
1023
+ TestConstructorClass instance2 = (TestConstructorClass)singleParamDelegate(
1024
+ new object[] { 99 }
1025
+ );
1026
+ Assert.AreEqual(99, instance2.Value1);
1027
+ Assert.AreEqual("single", instance2.Value2);
1028
+ }
1029
+
1030
+ [Test]
1031
+ public void GetParameterlessConstructor()
1032
+ {
1033
+ Func<TestConstructorClass> constructor =
1034
+ ReflectionHelpers.GetParameterlessConstructor<TestConstructorClass>();
1035
+ Assert.IsNotNull(constructor);
1036
+
1037
+ for (int i = 0; i < 100; i++)
1038
+ {
1039
+ TestConstructorClass instance = constructor();
1040
+ Assert.IsNotNull(instance);
1041
+ Assert.AreEqual(0, instance.Value1);
1042
+ Assert.AreEqual("default", instance.Value2);
1043
+ Assert.AreEqual(false, instance.Value3);
1044
+ }
1045
+ }
1046
+
1047
+ [Test]
1048
+ public void CreateGenericInstance()
1049
+ {
1050
+ object intGeneric = ReflectionHelpers.CreateGenericInstance<object>(
1051
+ typeof(GenericTestClass<>),
1052
+ new[] { typeof(int) },
1053
+ 42
1054
+ );
1055
+
1056
+ Assert.IsNotNull(intGeneric);
1057
+ Assert.IsInstanceOf<GenericTestClass<int>>(intGeneric);
1058
+ Assert.AreEqual(42, ((GenericTestClass<int>)intGeneric).Value);
1059
+
1060
+ object stringGeneric = ReflectionHelpers.CreateGenericInstance<object>(
1061
+ typeof(GenericTestClass<>),
1062
+ new[] { typeof(string) },
1063
+ "hello"
1064
+ );
1065
+
1066
+ Assert.IsNotNull(stringGeneric);
1067
+ Assert.IsInstanceOf<GenericTestClass<string>>(stringGeneric);
1068
+ Assert.AreEqual("hello", ((GenericTestClass<string>)stringGeneric).Value);
1069
+ }
1070
+
1071
+ [Test]
1072
+ public void GetGenericParameterlessConstructor()
1073
+ {
1074
+ Func<object> constructor = ReflectionHelpers.GetGenericParameterlessConstructor<object>(
1075
+ typeof(GenericTestClass<>),
1076
+ typeof(int)
1077
+ );
1078
+
1079
+ Assert.IsNotNull(constructor);
1080
+
1081
+ object instance = constructor();
1082
+ Assert.IsNotNull(instance);
1083
+ Assert.IsInstanceOf<GenericTestClass<int>>(instance);
1084
+ }
1085
+
1086
+ [Test]
1087
+ public void CreateStructInstance()
1088
+ {
1089
+ TestConstructorStruct structInstance =
1090
+ ReflectionHelpers.CreateInstance<TestConstructorStruct>(123);
1091
+ Assert.AreEqual(123, structInstance.Value);
1092
+ }
1093
+
1094
+ [Test]
1095
+ public void GetPropertyGetterStatic()
1096
+ {
1097
+ PropertyInfo staticProp = typeof(TestPropertyClass).GetProperty(
1098
+ nameof(TestPropertyClass.StaticProperty)
1099
+ );
1100
+ PropertyInfo staticStringProp = typeof(TestPropertyClass).GetProperty(
1101
+ nameof(TestPropertyClass.StaticStringProperty)
1102
+ );
1103
+ PropertyInfo staticReadOnlyProp = typeof(TestPropertyClass).GetProperty(
1104
+ nameof(TestPropertyClass.StaticReadOnlyProperty)
1105
+ );
1106
+
1107
+ Func<object, object> staticGetter = ReflectionHelpers.GetPropertyGetter(staticProp);
1108
+ Func<object, object> staticStringGetter = ReflectionHelpers.GetPropertyGetter(
1109
+ staticStringProp
1110
+ );
1111
+ Func<object, object> staticReadOnlyGetter = ReflectionHelpers.GetPropertyGetter(
1112
+ staticReadOnlyProp
1113
+ );
1114
+
1115
+ // Test initial values
1116
+ Assert.AreEqual(50, staticGetter(null));
1117
+ Assert.AreEqual("static", staticStringGetter(null));
1118
+ Assert.AreEqual(999, staticReadOnlyGetter(null));
1119
+
1120
+ // Test after changing values
1121
+ TestPropertyClass.StaticProperty = 100;
1122
+ TestPropertyClass.StaticStringProperty = "changed";
1123
+
1124
+ Assert.AreEqual(100, staticGetter(null));
1125
+ Assert.AreEqual("changed", staticStringGetter(null));
1126
+ Assert.AreEqual(999, staticReadOnlyGetter(null)); // Read-only shouldn't change
1127
+ }
1128
+
1129
+ [Test]
1130
+ public void GetPropertyGetterInstance()
1131
+ {
1132
+ TestPropertyClass testObj = new();
1133
+ PropertyInfo instanceProp = typeof(TestPropertyClass).GetProperty(
1134
+ nameof(TestPropertyClass.InstanceProperty)
1135
+ );
1136
+ PropertyInfo instanceStringProp = typeof(TestPropertyClass).GetProperty(
1137
+ nameof(TestPropertyClass.InstanceStringProperty)
1138
+ );
1139
+ PropertyInfo instanceReadOnlyProp = typeof(TestPropertyClass).GetProperty(
1140
+ nameof(TestPropertyClass.InstanceReadOnlyProperty)
1141
+ );
1142
+
1143
+ Func<object, object> instanceGetter = ReflectionHelpers.GetPropertyGetter(instanceProp);
1144
+ Func<object, object> instanceStringGetter = ReflectionHelpers.GetPropertyGetter(
1145
+ instanceStringProp
1146
+ );
1147
+ Func<object, object> instanceReadOnlyGetter = ReflectionHelpers.GetPropertyGetter(
1148
+ instanceReadOnlyProp
1149
+ );
1150
+
1151
+ // Test initial values
1152
+ Assert.AreEqual(25, instanceGetter(testObj));
1153
+ Assert.AreEqual("instance", instanceStringGetter(testObj));
1154
+ Assert.AreEqual(888, instanceReadOnlyGetter(testObj));
1155
+
1156
+ // Test after changing values
1157
+ testObj.InstanceProperty = 200;
1158
+ testObj.InstanceStringProperty = "modified";
1159
+
1160
+ Assert.AreEqual(200, instanceGetter(testObj));
1161
+ Assert.AreEqual("modified", instanceStringGetter(testObj));
1162
+ Assert.AreEqual(888, instanceReadOnlyGetter(testObj)); // Read-only shouldn't change
1163
+ }
1164
+
1165
+ [Test]
1166
+ public void GetStaticPropertyGetter()
1167
+ {
1168
+ Func<int> staticGetter = ReflectionHelpers.GetStaticPropertyGetter<int>(
1169
+ typeof(TestPropertyClass).GetProperty(nameof(TestPropertyClass.StaticProperty))
1170
+ );
1171
+
1172
+ Func<string> staticStringGetter = ReflectionHelpers.GetStaticPropertyGetter<string>(
1173
+ typeof(TestPropertyClass).GetProperty(
1174
+ nameof(TestPropertyClass.StaticStringProperty)
1175
+ )
1176
+ );
1177
+
1178
+ Assert.AreEqual(TestPropertyClass.StaticProperty, staticGetter());
1179
+ Assert.AreEqual(TestPropertyClass.StaticStringProperty, staticStringGetter());
1180
+
1181
+ TestPropertyClass.StaticProperty = 777;
1182
+ TestPropertyClass.StaticStringProperty = "new value";
1183
+
1184
+ Assert.AreEqual(777, staticGetter());
1185
+ Assert.AreEqual("new value", staticStringGetter());
1186
+ }
1187
+
1188
+ [Test]
1189
+ public void GetAllLoadedAssemblies()
1190
+ {
1191
+ Assembly[] assemblies = ReflectionHelpers.GetAllLoadedAssemblies().ToArray();
1192
+ Assert.IsNotNull(assemblies);
1193
+ Assert.Greater(assemblies.Length, 0);
1194
+ Assert.IsTrue(assemblies.All(a => a != null));
1195
+ Assert.IsTrue(assemblies.All(a => !a.IsDynamic));
1196
+ }
1197
+
1198
+ [Test]
1199
+ public void GetAllLoadedTypes()
1200
+ {
1201
+ Type[] types = ReflectionHelpers.GetAllLoadedTypes().Take(100).ToArray();
1202
+ Assert.IsNotNull(types);
1203
+ Assert.Greater(types.Length, 0);
1204
+ Assert.IsTrue(types.All(t => t != null));
1205
+ }
1206
+
1207
+ [Test]
1208
+ public void GetTypesFromAssembly()
1209
+ {
1210
+ Assembly testAssembly = typeof(ReflectionHelperTests).Assembly;
1211
+ Type[] types = ReflectionHelpers.GetTypesFromAssembly(testAssembly).ToArray();
1212
+
1213
+ Assert.IsNotNull(types);
1214
+ Assert.Greater(types.Length, 0);
1215
+ Assert.IsTrue(types.Contains(typeof(ReflectionHelperTests)));
1216
+ Assert.IsTrue(types.Contains(typeof(TestAttributeClass)));
1217
+ Assert.IsTrue(types.Contains(typeof(TestMethodClass)));
1218
+ }
1219
+
1220
+ [Test]
1221
+ public void GetTypesFromAssemblyName()
1222
+ {
1223
+ Type[] types = ReflectionHelpers
1224
+ .GetTypesFromAssemblyName("System.Core")
1225
+ .Take(10)
1226
+ .ToArray();
1227
+ Assert.IsNotNull(types);
1228
+ // May be empty on some platforms, but should not throw
1229
+ }
1230
+
1231
+ [Test]
1232
+ public void GetTypesWithAttribute()
1233
+ {
1234
+ Type[] typesWithDescAttr = ReflectionHelpers
1235
+ .GetTypesWithAttribute<DescriptionAttribute>()
1236
+ .ToArray();
1237
+ Assert.IsNotNull(typesWithDescAttr);
1238
+ Assert.IsTrue(typesWithDescAttr.Contains(typeof(TestAttributeClass)));
1239
+
1240
+ Type[] typesByType = ReflectionHelpers
1241
+ .GetTypesWithAttribute(typeof(DescriptionAttribute))
1242
+ .ToArray();
1243
+ Assert.IsNotNull(typesByType);
1244
+ Assert.IsTrue(typesByType.Contains(typeof(TestAttributeClass)));
1245
+ }
1246
+
1247
+ [Test]
1248
+ public void HasAttributeSafe()
1249
+ {
1250
+ Type testType = typeof(TestAttributeClass);
1251
+ FieldInfo staticField = testType.GetField(
1252
+ nameof(TestAttributeClass.StaticFieldWithAttribute)
1253
+ );
1254
+ MethodInfo instanceMethod = testType.GetMethod(
1255
+ nameof(TestAttributeClass.InstanceMethodWithAttribute)
1256
+ );
1257
+
1258
+ Assert.IsTrue(ReflectionHelpers.HasAttributeSafe<ReflectionTestAttribute>(testType));
1259
+ Assert.IsTrue(ReflectionHelpers.HasAttributeSafe<ReflectionTestAttribute>(staticField));
1260
+ Assert.IsTrue(
1261
+ ReflectionHelpers.HasAttributeSafe<ReflectionTestAttribute>(instanceMethod)
1262
+ );
1263
+
1264
+ Assert.IsTrue(
1265
+ ReflectionHelpers.HasAttributeSafe(testType, typeof(ReflectionTestAttribute))
1266
+ );
1267
+ Assert.IsTrue(
1268
+ ReflectionHelpers.HasAttributeSafe(staticField, typeof(ReflectionTestAttribute))
1269
+ );
1270
+ Assert.IsTrue(
1271
+ ReflectionHelpers.HasAttributeSafe(instanceMethod, typeof(ReflectionTestAttribute))
1272
+ );
1273
+
1274
+ // Test with types that don't have attributes
1275
+ Assert.IsFalse(
1276
+ ReflectionHelpers.HasAttributeSafe<ReflectionTestAttribute>(typeof(TestMethodClass))
1277
+ );
1278
+ Assert.IsFalse(
1279
+ ReflectionHelpers.HasAttributeSafe(
1280
+ typeof(TestMethodClass),
1281
+ typeof(ReflectionTestAttribute)
1282
+ )
1283
+ );
1284
+
1285
+ // Test with null (should return false, not throw)
1286
+ Assert.IsFalse(ReflectionHelpers.HasAttributeSafe<ReflectionTestAttribute>(null));
1287
+ Assert.IsFalse(
1288
+ ReflectionHelpers.HasAttributeSafe(null, typeof(ReflectionTestAttribute))
1289
+ );
1290
+ }
1291
+
1292
+ [Test]
1293
+ public void GetAttributeSafe()
1294
+ {
1295
+ Type testType = typeof(TestAttributeClass);
1296
+ FieldInfo instanceField = testType.GetField(
1297
+ nameof(TestAttributeClass.InstanceFieldWithAttribute)
1298
+ );
1299
+
1300
+ ReflectionTestAttribute classAttr =
1301
+ ReflectionHelpers.GetAttributeSafe<ReflectionTestAttribute>(testType);
1302
+ Assert.IsNotNull(classAttr);
1303
+ Assert.AreEqual("ClassLevel", classAttr.Name);
1304
+ Assert.AreEqual(10, classAttr.Value);
1305
+
1306
+ ReflectionTestAttribute fieldAttr =
1307
+ ReflectionHelpers.GetAttributeSafe<ReflectionTestAttribute>(instanceField);
1308
+ Assert.IsNotNull(fieldAttr);
1309
+ Assert.AreEqual("InstanceField", fieldAttr.Name);
1310
+ Assert.AreEqual(5, fieldAttr.Value);
1311
+
1312
+ // Test non-generic version
1313
+ Attribute classAttrObj = ReflectionHelpers.GetAttributeSafe(
1314
+ testType,
1315
+ typeof(ReflectionTestAttribute)
1316
+ );
1317
+ Assert.IsNotNull(classAttrObj);
1318
+ Assert.IsInstanceOf<ReflectionTestAttribute>(classAttrObj);
1319
+
1320
+ // Test with null
1321
+ Assert.IsNull(ReflectionHelpers.GetAttributeSafe<ReflectionTestAttribute>(null));
1322
+ Assert.IsNull(
1323
+ ReflectionHelpers.GetAttributeSafe(null, typeof(ReflectionTestAttribute))
1324
+ );
1325
+ }
1326
+
1327
+ [Test]
1328
+ public void GetAllAttributesSafe()
1329
+ {
1330
+ Type testType = typeof(TestAttributeClass);
1331
+ PropertyInfo instanceProperty = testType.GetProperty(
1332
+ nameof(TestAttributeClass.InstancePropertyWithAttribute)
1333
+ );
1334
+
1335
+ ReflectionTestAttribute[] typeAttrs = ReflectionHelpers
1336
+ .GetAllAttributesSafe<ReflectionTestAttribute>(testType)
1337
+ .ToArray();
1338
+ Assert.IsNotNull(typeAttrs);
1339
+ Assert.AreEqual(1, typeAttrs.Length);
1340
+ Assert.AreEqual("ClassLevel", typeAttrs[0].Name);
1341
+
1342
+ ReflectionTestAttribute[] propAttrs = ReflectionHelpers
1343
+ .GetAllAttributesSafe<ReflectionTestAttribute>(instanceProperty)
1344
+ .ToArray();
1345
+ Assert.IsNotNull(propAttrs);
1346
+ Assert.AreEqual(1, propAttrs.Length);
1347
+ Assert.AreEqual("InstanceProperty", propAttrs[0].Name);
1348
+
1349
+ // Test non-generic version
1350
+ Attribute[] allTypeAttrs = ReflectionHelpers.GetAllAttributesSafe(testType).ToArray();
1351
+ Assert.IsNotNull(allTypeAttrs);
1352
+ Assert.Greater(allTypeAttrs.Length, 0);
1353
+
1354
+ Attribute[] allPropAttrs = ReflectionHelpers
1355
+ .GetAllAttributesSafe(instanceProperty, typeof(ReflectionTestAttribute))
1356
+ .ToArray();
1357
+ Assert.IsNotNull(allPropAttrs);
1358
+ Assert.AreEqual(1, allPropAttrs.Length);
1359
+
1360
+ // Test with null
1361
+ Assert.AreEqual(
1362
+ 0,
1363
+ ReflectionHelpers.GetAllAttributesSafe<ReflectionTestAttribute>(null).Length
1364
+ );
1365
+ Assert.AreEqual(0, ReflectionHelpers.GetAllAttributesSafe(null).Length);
1366
+ }
1367
+
1368
+ [Test]
1369
+ public void GetAllAttributeValuesSafe()
1370
+ {
1371
+ Type testType = typeof(TestAttributeClass);
1372
+ Dictionary<string, object> attrValues = ReflectionHelpers.GetAllAttributeValuesSafe(
1373
+ testType
1374
+ );
1375
+
1376
+ Assert.IsNotNull(attrValues);
1377
+ Assert.IsTrue(attrValues.ContainsKey("ReflectionTest"));
1378
+ Assert.IsInstanceOf<ReflectionTestAttribute>(attrValues["ReflectionTest"]);
1379
+
1380
+ // Test with null
1381
+ Dictionary<string, object> nullResult = ReflectionHelpers.GetAllAttributeValuesSafe(
1382
+ null
1383
+ );
1384
+ Assert.IsNotNull(nullResult);
1385
+ Assert.AreEqual(0, nullResult.Count);
1386
+ }
1387
+
1388
+ [Test]
1389
+ public void GetMembersWithAttributeSafe()
1390
+ {
1391
+ Type testType = typeof(TestAttributeClass);
1392
+
1393
+ MethodInfo[] methods = ReflectionHelpers
1394
+ .GetMethodsWithAttributeSafe<ReflectionTestAttribute>(testType)
1395
+ .ToArray();
1396
+ Assert.IsNotNull(methods);
1397
+ Assert.Greater(methods.Length, 0);
1398
+ Assert.IsTrue(
1399
+ methods.Any(m => m.Name == nameof(TestAttributeClass.StaticMethodWithAttribute))
1400
+ );
1401
+ Assert.IsTrue(
1402
+ methods.Any(m => m.Name == nameof(TestAttributeClass.InstanceMethodWithAttribute))
1403
+ );
1404
+
1405
+ PropertyInfo[] properties = ReflectionHelpers
1406
+ .GetPropertiesWithAttributeSafe<ReflectionTestAttribute>(testType)
1407
+ .ToArray();
1408
+ Assert.IsNotNull(properties);
1409
+ Assert.Greater(properties.Length, 0);
1410
+ Assert.IsTrue(
1411
+ properties.Any(p =>
1412
+ p.Name == nameof(TestAttributeClass.StaticPropertyWithAttribute)
1413
+ )
1414
+ );
1415
+
1416
+ FieldInfo[] fields = ReflectionHelpers
1417
+ .GetFieldsWithAttributeSafe<ReflectionTestAttribute>(testType)
1418
+ .ToArray();
1419
+ Assert.IsNotNull(fields);
1420
+ Assert.Greater(fields.Length, 0);
1421
+ Assert.IsTrue(
1422
+ fields.Any(f => f.Name == nameof(TestAttributeClass.StaticFieldWithAttribute))
1423
+ );
1424
+
1425
+ // Test with null
1426
+ Assert.AreEqual(
1427
+ 0,
1428
+ ReflectionHelpers.GetMethodsWithAttributeSafe<ReflectionTestAttribute>(null).Length
1429
+ );
1430
+ Assert.AreEqual(
1431
+ 0,
1432
+ ReflectionHelpers
1433
+ .GetPropertiesWithAttributeSafe<ReflectionTestAttribute>(null)
1434
+ .Length
1435
+ );
1436
+ Assert.AreEqual(
1437
+ 0,
1438
+ ReflectionHelpers.GetFieldsWithAttributeSafe<ReflectionTestAttribute>(null).Length
1439
+ );
1440
+ }
1441
+
1442
+ [Test]
1443
+ public void LoadStaticPropertiesForType()
1444
+ {
1445
+ Dictionary<string, PropertyInfo> staticProperties =
1446
+ ReflectionHelpers.LoadStaticPropertiesForType<TestPropertyClass>();
1447
+ Assert.IsNotNull(staticProperties);
1448
+
1449
+ // Note: This method looks for static properties that return the same type as the class
1450
+ // Our TestPropertyClass doesn't have static properties that return TestPropertyClass,
1451
+ // so the result should be empty, but the method should not throw
1452
+ Assert.IsNotNull(staticProperties);
1453
+ }
1454
+
1455
+ [Test]
1456
+ public void LoadStaticFieldsForType()
1457
+ {
1458
+ Dictionary<string, FieldInfo> staticFields =
1459
+ ReflectionHelpers.LoadStaticFieldsForType<TestPropertyClass>();
1460
+ Assert.IsNotNull(staticFields);
1461
+
1462
+ // Note: This method looks for static fields that are of the same type as the class
1463
+ // Our TestPropertyClass doesn't have such fields, so the result should be empty,
1464
+ // but the method should not throw
1465
+ Assert.IsNotNull(staticFields);
1466
+ }
1467
+
1468
+ [Test]
1469
+ public void IsAttributeDefined()
1470
+ {
1471
+ Type testType = typeof(TestAttributeClass);
1472
+ FieldInfo testField = testType.GetField(
1473
+ nameof(TestAttributeClass.InstanceFieldWithAttribute)
1474
+ );
1475
+
1476
+ // Test the extension method version
1477
+ Assert.IsTrue(testType.IsAttributeDefined(out ReflectionTestAttribute typeAttr));
1478
+ Assert.IsNotNull(typeAttr);
1479
+ Assert.AreEqual("ClassLevel", typeAttr.Name);
1480
+ Assert.AreEqual(10, typeAttr.Value);
1481
+
1482
+ Assert.IsTrue(testField.IsAttributeDefined(out ReflectionTestAttribute fieldAttr));
1483
+ Assert.IsNotNull(fieldAttr);
1484
+ Assert.AreEqual("InstanceField", fieldAttr.Name);
1485
+ Assert.AreEqual(5, fieldAttr.Value);
1486
+
1487
+ // Test with type that doesn't have the attribute
1488
+ Type methodType = typeof(TestMethodClass);
1489
+ Assert.IsFalse(methodType.IsAttributeDefined(out ReflectionTestAttribute noAttr));
1490
+ Assert.IsNull(noAttr);
1491
+ }
531
1492
  }
532
1493
  }