查看,clr via c# 程序集加载和反射(1)

8,发现类型的成员:

字段,构造器,方法,属性,事件,嵌套类型都可以作为类型成员.其包含在抽象类MemberInfo中,封装了所有类型都有的一组属性.

MemeberInfo的派生列表:

System.Reflection.MemberInfo
    System.Reflection.EventInFo

System.Reflection.FieldInfo
    System.Reflection.MethodBase
           System.Reflection.ConstructorInfo

System.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有啥用,感觉节约空间有限.

clr via c# 程序集加载和反射(2)的更多相关文章

  1. clr via c# 程序集加载和反射集(一)

    1,程序集加载---弱的程序集可以加载强签名的程序集,但是不可相反.否则引用会报错!(但是,反射是没问题的) //获取当前类的Assembly Assembly.GetEntryAssembly() ...

  2. CLR中的程序集加载

    CLR中的程序集加载 本次来讨论一下基于.net平台的CLR中的程序集加载的机制: [注:由于.net已经开源,可利用vs2015查看c#源码的具体实现] 在运行时,JIT编译器利用程序集的TypeR ...

  3. 重温CLR(十七)程序集加载和反射

    本章主要讨论在编译时对一个类型一无所知的情况下,如何在运行时发现类型的信息.创建类型的实例以及访问类型的成员.可利用本章讲述的内容创建动态可扩展应用程序. 反射使用的典型场景一般是由一家公司创建宿主应 ...

  4. 【C#进阶系列】23 程序集加载和反射

    程序集加载 程序集加载,CLR使用System.Reflection.Assembly.Load静态方法,当然这个方法我们自己也可以显式调用. 还有一个Assembly.LoadFrom方法加载指定路 ...

  5. 【C#】解析C#程序集的加载和反射

    目录结构: contents structure [+] 程序集 程序集的加载 发现程序集中的类型 反射对类型成员的常规操作 发现类型的成员 创建类型的实例 绑定句柄减少进程的内存消耗 解析自定义特性 ...

  6. .NET 的程序集加载上下文

    原文:.NET 的程序集加载上下文 我们编写的 .NET 应用程序会使用到各种各样的依赖库.我们都知道 CLR 会在一些路径下帮助我们程序找到依赖,但如果我们需要手动控制程序集加载路径的话,需要了解程 ...

  7. Clr Via C#读书笔记---程序集的加载和反射

    #1 加载程序集 Assembly.Load: public class Assembly { public static Assembly Load(AssemblyName assemblyRef ...

  8. .net 程序集的加载与反射

    一. 程序集的加载: 在CLR内部使用System.Reflection.Assembly类的静态LoadFrom方法尝试加载程序集. LoadFrom方法在内部调用Assembly的Load方法,将 ...

  9. CLR是如何被加载并工作的

    当运行Windows应用程序的时候,CLR总是默默地为服务着.CLR到底是如何被加载并运行呢? 首先,Microsoft专门为CLR定义了一个标准的COM接口. 安装某个版本的.NET Framewo ...

随机推荐

  1. MySql主要性能指标说明

    在项目当中数据库一般都会成为主要的性能与负载瓶颈,那么针对数据库各项性能指标的监控与对应的优化是开发与运维人员需要面对的主要工作,而且这部分的工作会贯穿项目从开发到运行的整个周期里. 这篇文章中我们对 ...

  2. 为BlueLake主题增加自定义icon图标

    一.前言 hexo 的 Bluelake 主题是我一直在用的,简单大方,很喜欢.但最近有了添加自定义 icon 图标的需求,比如,添加 "地址"."扫一扫".& ...

  3. (转) XSS Attacks – Exploiting XSS Filter

    中文翻译: from wooyun'drops 0x00 前言 这又是一篇来自全职赏金猎人Masato kinugawa的神作.一次双杀,用一篇报告拿下了两个CVE,分别是CVE-2015-6144和 ...

  4. 个人作业四——Alpha测试

    个人作业四--Alpha测试 这个作业属于哪个课程 软件工程 这个作业要求在哪里 作业要求 团队名称 GP工作室 这个作业的目标 对其他小组的项目进行测试 测试人员 许佳文 学号 2017310242 ...

  5. android开发实战-记账本APP(一)

    记账本开发流程: 对于一个记账本的初步开发而言,我实现的功能有: ①实现一个记账本的页面 ②可以添加数据并更新到页面中 ③可以将数据信息以图表的形式展现 (一)首先,制作一个记账本的页面. ①在系统自 ...

  6. 解决---MISCONF Redis被配置为保存RDB快照,但目前无法在磁盘上存留。可能修改数据集的命令被禁用。请检查Redis日志,了解有关错误的详细信息。

    解决---MISCONF Redis被配置为保存RDB快照,但目前无法在磁盘上存留.可能修改数据集的命令被禁用.请检查Redis日志,了解有关错误的详细信息. 出现bug: 在学习celery,将数据 ...

  7. zerotier 远程办公方案

    武汉新肺炎疫情下,搞得人心惶惶.很多公司都要求前期远程办公 我厂日常有在家远程应急支持的情况,所以公司很早就有VPN服务.只需要申请VPN服务,开通之后就可以连上公司各种公共资源. 然而对于一些非公共 ...

  8. Hyper-V虚拟机设置外部网络访问

    在Hyper-V管理器中新建一个虚拟交换机,类型为 内部 ,修改名称为 nat 在虚拟机的设置页面中,将网络适配器设置为新建的虚拟交换机 nat 打开win10->控制面板->网络和共享中 ...

  9. 一段关于用户登录 和乘法表的python代码

    用户登录代码(低配): name = 1password =11counter = 1while counter <3 : a = int(input ('name:')) #注意这里 inpu ...

  10. (转)KL散度的理解

    KL散度(KL divergence) 全称:Kullback-Leibler Divergence. 用途:比较两个概率分布的接近程度.在统计应用中,我们经常需要用一个简单的,近似的概率分布 f * ...