基本反射使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 [MenuItem("Tools/测试反射" ) ] public static void TestReflection () { TestForReflection test = new TestForReflection(); test.isTest = true ; test.Id = 1 ; test.Name = "test" ; object nameValue = null ; Type testType = test.GetType(); MemberInfo[] members = testType.GetMember("Name" , BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); while (members == null || members.Length == 0 ) { testType = testType.BaseType; if (testType == null ) { return ; } members = testType.GetMember("Name" ,BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); } switch (members[0 ].MemberType) { case MemberTypes.Field: nameValue = testType.GetField("Name" , BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static).GetValue(test); break ; case MemberTypes.Property: nameValue = testType.GetProperty("Name" ,BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static).GetValue (test); break ; default : break ; } Debug.Log(nameValue); } public class TestForReflection { public int Id; public string Name; public bool isTest; }
反射得到属性和变量的方法封装 将上述反射方法封装一下,再进行调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 [MenuItem("Tools/测试反射" ) ] public static void TestReflection (){ TestForReflection test = new TestForReflection(); test.isTest = true ; test.Id = 1 ; test.Name = "test" ; object nameValue = null ; nameValue = GetMemberValue(test, "Name" ); Debug.Log(nameValue); } private static object GetMemberValue (object obj,string memberName, BindingFlags bindingAttr = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static ){ Type testType = obj.GetType(); MemberInfo[] members = testType.GetMember(memberName, bindingAttr); while (members == null || members.Length == 0 ) { testType = testType.BaseType; if (testType == null ) { return null ; } members = testType.GetMember(memberName, bindingAttr); } switch (members[0 ].MemberType) { case MemberTypes.Field: return testType.GetField(memberName, bindingAttr).GetValue(obj); case MemberTypes.Property: return testType.GetProperty(memberName, bindingAttr).GetValue(obj); default : return null ; } }
反射list 我们给TestForReflection
添加一个List<string>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 [MenuItem("Tools/测试反射" ) ] public static void TestReflection () { TestForReflection test = new TestForReflection(); test.isTest = true ; test.Id = 1 ; test.Name = "test" ; test.testList = new List<string >() { "1" , "2" , "3" }; object list = GetMemberValue(test,"testList" ); int listCount = System.Convert.ToInt32(list.GetType().InvokeMember("get_Count" , BindingFlags.Default | BindingFlags.InvokeMethod, null , list, new object [] { })); for (int i = 0 ; i < listCount; i++) { object item = list.GetType().InvokeMember("get_Item" ,BindingFlags.Default | BindingFlags.InvokeMethod,null ,list, new object [] { i }); Debug.Log(item); } } public class TestForReflection { public int Id; public string Name; public bool isTest; public List<string > testList; }
我们先用list.GetType()
得到list的Type,也就是System.Collections.Generic.List
1[System.String]`
然后使用InvokeMember
方法,反射调用List类的"get_Count"
方法,当我们使用InvokeMember
方法时,它的参数有:
public object? InvokeMember (string name, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder? binder, object? target, object?[]? args);
第一个参数就是"get_Count"
,第二个参数是BindingFlags.Default | BindingFlags.InvokeMethod
,这个也算是固定用法,BindingFlags.InvokeMethod
就是配合InvokeMember
方法的。第三个参数Binder
我们设为null,第四个参数target我们需要传一个有实例的object,因为"get_Count"
并不是一个静态方法,如果我们要调用就必须传一个target。第五个参数我们传一个空的数组,一般这个参数数组就是用来传"get_Count"
所需要的参数的。
反射自定义class的list 上面的例子我们反射的是List<string>
,在实际使用中,我们大多数情况下会反射自定义类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 [MenuItem("Tools/测试反射" ) ] public static void TestReflection () { TestForReflection test = new TestForReflection(); test.isTest = true ; test.Id = 1 ; test.Name = "test" ; test.testList = new List<string >() { "1" , "2" , "3" }; test.testList2 = new List<TestForListReflection> { new TestForListReflection{ Id = 1 , Name = "test1" }, new TestForListReflection{ Id = 2 , Name = "test2" }, new TestForListReflection{ Id = 3 , Name = "test3" }, }; object list2 = GetMemberValue(test, "testList2" ); int list2Count = System.Convert.ToInt32(list2.GetType().InvokeMember("get_Count" , BindingFlags.Default | BindingFlags.InvokeMethod, null , list2, new object [] { })); for (int i = 0 ; i < list2Count; i++) { object item = list2.GetType().InvokeMember("get_Item" , BindingFlags.Default | BindingFlags.InvokeMethod, null , list2, new object [] { i }); object id = GetMemberValue(item, "Id" ); object name = GetMemberValue(item, "Name" ); Debug.Log(id + " " + name); } } public class TestForReflection { public int Id; public string Name; public bool isTest; public List<string > testList; public List<TestForListReflection> testList2; } public class TestForListReflection { public int Id { get ; set ; } public string Name { get ; set ; } }
通过反射创建实例 封装Activator.CreateInstance 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 private static object CreateClassInstance (string name ){ object obj = null ; Type type = null ; foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) { Type curType = asm.GetType(name); if (curType != null ) { type = curType; break ; } } if (type != null ) { obj = Activator.CreateInstance(type); } return obj; }
通过反射创建实例并赋值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 [MenuItem("Tools/测试反射创建" ) ] public static void TestReflection2 () { object obj = CreateClassInstance("TestForReflection" ); PropertyInfo idInfo = obj.GetType().GetProperty("Id" ); idInfo.SetValue(obj, Convert.ToInt32("11" )); PropertyInfo nameInfo = obj.GetType().GetProperty("Name" ); nameInfo.SetValue(obj,"ATAO" ); PropertyInfo boolInfo = obj.GetType().GetProperty("isTest" ); boolInfo.SetValue(obj, Convert.ToBoolean("true" )); PropertyInfo floatInfo = obj.GetType().GetProperty("Height" ); floatInfo.SetValue(obj, Convert.ToSingle("12.5" )); PropertyInfo enumInfo = obj.GetType().GetProperty("TestEn" ); object enumValue = TypeDescriptor.GetConverter(enumInfo.PropertyType).ConvertFromInvariantString("Test1" ); enumInfo.SetValue(obj, enumValue); TestForReflection test = obj as TestForReflection; Debug.Log(test.Id + " " + test.Name + " " + test.isTest + " " + test.Height + " " + test.TestEn); } public class TestForReflection { public int Id { get ; set ; } public string Name { get ; set ; } public bool isTest { get ; set ; } public float Height { get ; set ; } public TestEnum TestEn { get ; set ; } } public enum TestEnum{ None = 0 , Test1 = 1 , Test2 = 2 , }
注意Enum的转换方式:使用TypeDescriptor.GetConverter
得到Enum的转换器,然后调用ConvertFromInvariantString
只有这样我们才能调用PropertyInfo.SetValue
来设置枚举的值
封装SetValue方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 [MenuItem("Tools/测试反射创建" ) ] public static void TestReflection2 (){ object obj = CreateClassInstance("TestForReflection" ); PropertyInfo idInfo = obj.GetType().GetProperty("Id" ); SetValue(idInfo, obj, "11" , "int" ); PropertyInfo nameInfo = obj.GetType().GetProperty("Name" ); SetValue(nameInfo, obj, "ATAO" , "string" ); PropertyInfo boolInfo = obj.GetType().GetProperty("isTest" ); SetValue(boolInfo, obj, "true" , "bool" ); PropertyInfo floatInfo = obj.GetType().GetProperty("Height" ); SetValue(floatInfo, obj, "12.3" , "float" ); PropertyInfo enumInfo = obj.GetType().GetProperty("TestEn" ); SetValue(enumInfo, obj, "Test2" , "enum" ); TestForReflection test = obj as TestForReflection; Debug.Log(test.Id + " " + test.Name + " " + test.isTest + " " + test.Height + " " + test.TestEn); } private static void SetValue (PropertyInfo info, object var , string value ,string type ){ object val = (object )value ; switch (type) { case "int" : val = Convert.ToInt32(val); break ; case "float" : val = Convert.ToSingle(val); break ; case "bool" : val = Convert.ToBoolean(val); break ; case "enum" : val = TypeDescriptor.GetConverter(info.PropertyType).ConvertFromInvariantString(val.ToString()); break ; } info.SetValue(var , val); }
通过反射创建List 通过反射创建普通List 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 [MenuItem("Tools/测试反射创建" ) ] public static void TestReflection2 () { object obj = CreateClassInstance("TestForReflection" ); Type stringType = typeof (string ); Type listType = typeof (List<>); Type listGenericType = listType.MakeGenericType(new System.Type[] { stringType }); object listObj = Activator.CreateInstance(listGenericType,new object [] {}); for (int i = 0 ; i < 3 ; i++) { string itemStr = "TestList" + i; listObj.GetType().InvokeMember("Add" ,BindingFlags.Default | BindingFlags.InvokeMethod,null ,listObj,new object [] {itemStr}); } obj.GetType().GetField("testList" ).SetValue(obj, listObj); TestForReflection test = obj as TestForReflection; test.testList.ForEach(x => { Debug.Log(x); }); } public class TestForReflection { public int Id { get ; set ; } public string Name { get ; set ; } public bool isTest { get ; set ; } public float Height { get ; set ; } public TestEnum TestEn { get ; set ; } public List<string > testList { get ; set ; } public List<TestForListReflection> testList2 { get ;set ; } }
注意看创建时使用的API
封装创建泛型ListType的方法 1 2 3 4 5 6 7 8 9 10 private static object CreateListGenericType (Type type ){ Type listGenericType = typeof (List<>).MakeGenericType(new System.Type[] {type}); return Activator.CreateInstance(listGenericType,new object [] {}); }
通过反射创建自定义类List 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 [MenuItem("Tools/测试反射创建" ) ] public static void TestReflection2 (){ object obj = CreateClassInstance("TestForReflection" ); object testListObj = CreateListGenericType(typeof (TestForListReflection)); for (int i = 0 ; i < 3 ; i++) { object testIns = CreateClassInstance("TestForListReflection" ); PropertyInfo testIdInfo = testIns.GetType().GetProperty("Id" ); SetValue(testIdInfo, testIns, i.ToString(), "int" ); PropertyInfo testNameInfo = testIns.GetType().GetProperty("Name" ); SetValue(testNameInfo, testIns, i.ToString() + "Test" ,"string" ); testListObj.GetType().InvokeMember("Add" ,BindingFlags.Default | BindingFlags.InvokeMethod,null ,testListObj,new object [] {testIns}); } obj.GetType().GetProperty("testList2" ).SetValue (obj, testListObj); TestForReflection test = obj as TestForReflection; test.testList2.ForEach(x => { Debug.Log(x.Id + " " + x.Name); }); }