8,发现类型的成员:
字段,构造器,方法,属性,事件,嵌套类型都可以作为类型成员.其包含在抽象类MemberInfo中,封装了所有类型都有的一组属性.
MemeberInfo的派生列表:
System.Reflection.MemberInfo
System.Reflection.EventInFoSystem.Reflection.FieldInfo
System.Reflection.MethodBase
System.Reflection.ConstructorInfoSystem.Reflection.MethodInfo
System.Reflection.PropertyInfo
System.Reflection.TypeInfo
- 显示Type的特性---在特性中已经有描述不再讲述
- 显示Type的MemberInfo
public static void DisplayType(Type t) { // Display(0, "Assembly:{0}", t.Assembly.FullName); //Display(0, "FullName:{0}", t.FullName); //DisplayAttribute(1, assembly); Display(0, ""); Display(0, "Type:{0}‘s Members:", t.Name); //DisplayAttribute(1, t); foreach (MemberInfo mi in t.GetTypeInfo().DeclaredMembers) { string typeName = string.Empty; if (mi is Type) typeName = "Nested Type"; if (mi is FieldInfo) typeName = "FieldInfo"; if (mi is MethodInfo) typeName = "MethodInfo"; if (mi is ConstructorInfo) typeName = "ConstructInfo"; if (mi is PropertyInfo) typeName = "PropertyInfo"; if (mi is EventInfo) typeName = "EventInfo"; Display(0,""); // DisplayAttribute(1, mi); Display(1, "{0}: {1}", mi.GetType().Name, mi); } }
MemberInfo的几个重要属性
Name:返回成员的名称
DeclaringType:返回声明了成员的Type的类型.比如mi的Declaring Type 是 t;
Module:返回声明了成员的模块:比如,上述mi的模块是ClrFromCSharp_2_2.exe,表示其在这个文件中.
CustomAttributes ,返回一个IEnumerable<CustomAttributeData> ,表示该成员的定制特性的一个实列的属性.
除了使用DeclaredMembers
还可以使用
GetDeclaredNestedType:返回嵌套类别
GetDeclaredField:返回字段
GetDeclaredMethod:返回方法
GetDeclaredProperty:返回属性
GetDeclaredEvent:返回事件
GetConstructor:返回特定的构造器
GetConstructors:返回所有构造器
对于构造器,方法,属性访问器方法(get,set),事件方法(add,remove)
- 可以调用GetParameterInfo获取ParameterInfo构成的数组,从而了解成员的参数的类型.还可以
- 查询只读属性ReturnParameter获得一个ParameterInfo的返回类型对象,表示成员的返回类型.
- 对于泛型对象,可以调用GetGenericArguments来获取他们的类型参数的集合
9,调用类型的成员.
使用InvokeMember方法调用成员的列子已经在前面讲过了.
1,使用绑定到成员并且调用:
internal sealed class SomeType//调试所有到的类 { public Int32 m_someField; public SomeType(ref Int32 x) { x *= 2; }//设定构造器使用Ref形参,需要Type.GetType("System.Int32&")or typeof(int).MakeRefType(); public override string ToString() { // throw new Exception("tostring err"); return m_someField.ToString(); } public Int32 SomeProp { get { return m_someField; } set { if (value < 1) throw new ArgumentOutOfRangeException();//模拟内部错误,注意,只有Release模式可以捕获,不然会出错. m_someField = value; } } public event EventHandler SomeEvent; private void NoCompilerWarnings() { SomeEvent.ToString(); } public int this[int index]//模拟索引器. { get { return m_someField + index; } set { m_someField = value + index; } } }
2,通过Member调用
public static void BindToMemberThenInvokeTheMember(Type t) { Display(0, MethodInfo.GetCurrentMethod().Name); //构造实列 object[] args = new object[] { 1 }; ConstructorInfo ctor = t.GetConstructor(new Type[] { typeof(int).MakeByRefType() }); Display(0, "Called before .ctor,args0 is {0}", args[0].ToString()); object obj=ctor.Invoke(args); Display(0, "Called after .ctor,args0 is {0}", args[0].ToString()); //读写字段 FieldInfo fi = t.GetTypeInfo().GetField("m_someField"); fi.SetValue(obj, 33); Display(0, "m_someField={0}", fi.GetValue(obj)); //调用方法 MethodInfo mi = t.GetTypeInfo().GetDeclaredMethod("ToString"); string s = mi.Invoke(obj, null) as string; Display(0, "tostring is " + s); //读写属性 PropertyInfo pi = t.GetTypeInfo().GetProperty("SomeProp"); try { t.InvokeMember("SomeProp", BindingFlags.SetProperty | BindingFlags.Public | BindingFlags.Instance, null, obj, new object[] { 0 }); } catch(TargetInvocationException e)//注意反射出错的类型.以及原类型引用. { if (e.InnerException.GetType() != typeof(ArgumentOutOfRangeException)) throw; Console.WriteLine("catched the Reflection error ,but in ReleaseMode"); } //读写索引器属性 PropertyInfo pi1 = t.GetTypeInfo().GetDeclaredProperty("Item"); pi1.SetValue(obj, 100, new object[] { 200 }); Display(0, pi1.GetValue(obj, new object[] { 200 }).ToString()); //为事件添加和删除委托 EventInfo ei = t.GetTypeInfo().GetDeclaredEvent("SomeEvent"); ei.AddEventHandler(obj, new EventHandler((sender, e) => Display(0, e.ToString()))); ei.RemoveEventHandler(obj, new EventHandler((sender, e) => Display(0, e.ToString()))); } }
3,通过CreateDelegate调用
public static void BindToMemberInvokeByDelegate(Type t) { //构造对象 object[] args = new object[] { 10 }; object obj = Activator.CreateInstance(t,args); //调用方法 MethodInfo mi = obj.GetType().GetTypeInfo().GetDeclaredMethod("ToString"); dynamic toString = mi.CreateDelegate(typeof(Func<string>), obj);//利用动态类型简化操作. string str = toString(); Display(0, str); //读写属性 PropertyInfo pi = obj.GetType().GetTypeInfo().GetDeclaredProperty("SomeProp"); dynamic setSomeProp =pi.SetMethod.CreateDelegate(typeof(Action<int>), obj); try { setSomeProp(0); } catch (ArgumentOutOfRangeException) { Console.WriteLine("Property set catch."); } setSomeProp(2); dynamic getSomeProp = pi.GetMethod.CreateDelegate(typeof(Func<int>), obj); Display(0, getSomeProp().ToString()); //向事件增加删除委托 EventInfo ei = t.GetTypeInfo().GetDeclaredEvent("SomeEvent"); dynamic addEventHandler = ei.AddMethod.CreateDelegate(typeof(Action<EventHandler>), obj); var removeEventHandler = (Action<EventHandler>)ei.RemoveMethod.CreateDelegate(typeof(Action<EventHandler>), obj); addEventHandler(new EventHandler((x, y) => Display(0, y.ToString()))); removeEventHandler(new EventHandler((x, y) => Display(0, y.ToString()))); }
1,使用dynamic简化类型转换.否则,需要类型转换后才能使用
2,使用GetMethod,SetMethod,AddMethod,RemoveMethod,来调用属性和事件的方法.
3,注意,异常变成了ArgumentOutOfRangeException
4,使用Dynamic的方法简化
public static void UseDynamicInvokeMember(Type t) { //构造对象 object[] args = new object[] { 10 }; dynamic obj = Activator.CreateInstance(t, args); //读写字段 try { obj.m_someField = 5; int v = obj.m_someField; Console.WriteLine("someField" + v); } catch(RuntimeBinderException e) { Display(0,"faild to access field:" + e.Message); } //调用方法 dynamic str = obj.ToString(); Display(0, "Tostring" + str); //读写属性 try { obj.SomeProp = 0; } catch (ArgumentOutOfRangeException) { Display(0, "Property set catch"); } obj.SomeProp = 2; dynamic val = obj.SomeProp; Display(0, "SomeProp" + val); obj.SomeEvent += new EventHandler((x, y) => Display(0, y.ToString())); obj.SomeEvent -= new EventHandler((x, y) => Display(0, y.ToString())); }
10,使用绑定句柄减少进程的内存消耗
在System定义了三个句柄
- RuntimeTypeHandle
- RuntimeFieldHandle
- RuntimeMethodHandle
- 将Type对象转换为一个RuntimeHandle对象,调用 Type.GetTypeHandle静态方法
- 将RuntimeTypeHandle转换为Type对象,调用 GetTypeFromHandle
- 要将FieldInfo转换为RuntimeFieldHandle,使用FieldInfo的实列只读属性FieldHandle
- 要将RuntimeFieldHandle转换为FieldInfo,调用FieldInfo.GetFieldFromHandle.
- 要将MethodInfo准换RuntimeMethodHandle,查新实列只读属性MethodHandle
- 使用MEthodINfo.GetMethodInfoFromHandle,返回MethodInfo对象
public static void CallHandleDifference() { BindingFlags c_bf = BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; showHeap(0, "Before doing something"); List<MethodBase> mis = new List<MethodBase>(); foreach (Type t in typeof(object).Assembly.ExportedTypes) { if (t.IsGenericTypeDefinition) continue; MethodBase[] mb = t.GetMethods(c_bf); mis.AddRange(mb); } Display(0, "# of methods={0:N0}", mis.Count); showHeap(0, "after building cache of MEthodInfo objects"); List<RuntimeMethodHandle> mish = mis.ConvertAll<RuntimeMethodHandle>(x => x.MethodHandle); showHeap(0, "holding Methodinfo and runtimehandle"); GC.KeepAlive(mis); mis = null; showHeap(0, "After free MethodInfo objects"); mis = mish.ConvertAll<MethodBase>(x => MethodBase.GetMethodFromHandle(x)); showHeap(0, "Re builds methodinfo objects"); GC.KeepAlive(mis); GC.KeepAlive(mish); showHeap(0,"end the thread..."); } private static void showHeap(int indent,string s) { Console.WriteLine("{0}Heap size={1,12:N0} - {2}", new string(‘ ‘, indent * 3), GC.GetTotalMemory(true), s);//该函数会回收内存. }
GC.GetTotalMemory(true)会回收内存.
不太明白这个Handle有啥用,感觉节约空间有限.
原文地址:https://www.cnblogs.com/frogkiller/p/12312611.html