CLR Via C# 读书笔记-第23章(程序集加载和反射)


第 23 章 程序集加载和反射

程序集的加载

  • Assembly.Load 加载程序集
  • Assembly.LoadFrom 加载指定路径名的程序集,内部原理就是通过GetAssemblyName获取程序集名,再利用Assembly.Load来加载,PS:这个路径可以是URL格式的

反射的性能

  • 通过字符串来标识类、成员字段、函数等,通过扫描元数据表进行大量的字符串搜索比较
  • 通过反射调用方法,需要将实参打包成数组,然后在线程栈解包,检查实参的正确类型,调用者权限等
  • 可以使用一下方法来避免直接调用函数
  1. 反射的类型派生自编译时已知类型,运行时构造反射类型实例,将对他的引用放到基类变量中,然后调用基类方法
  2. 反射的类型实现编译是已知接口,运行时构造反射类型实例,将对他的引用放到基类变量中,然后调用基类方法

反射发现程序集类型

  • Assembly.ExportedTypes 程序集所有public类型
  • 程序集中每个类型只有一个Type所有Type类型可以用==判断

构造类型实例

  • System.Activator.CreateInstance
  • System.Activator.CreateInstanceFrom 参数为string 返回ObjectHandle,需要调用Unwrap具体化
  • System.AppDomain实例方法CreateInstanceFrom AppDomain实例方法,指定在哪个AppDomain实例化
  • System.Reflection.ConstructorInfo实例方法Invoke
  • 创建数组 Array.CreateInstance
  • 创建委托 MethodInfo实例方法CreateDelegate
  • 创建字典
        public static void Main()
        {
            // 方法1
            Type dictType = typeof(Dictionary<,>);
            Type makedType = dictType.MakeGenericType(typeof(string), typeof(int));
            var dictObj = System.Activator.CreateInstance(makedType);
            Console.WriteLine(dictObj.GetType().Name);
            // 方法2
            var dict = System.Activator.CreateInstance<Dictionary<string, int>>();
            dict.Add("abc", 1);
        }

反射发现程序集类型的成员

注意一点, Type从MemberInfo派生,TypeInfo从Type派生

Type type = typeof(string);
TypeInfo typeInfo = type.GetTypeInfo();
foreach (var member in typeInfo.DeclaredMembers)
{
    if(member is Type)
    {
        Console.WriteLine($"{member.Name}是嵌套类型");
    }
    if (member is FieldInfo)
    {
        Console.WriteLine($"{member.Name}是字段");
    }
    if (member is MethodInfo)
    {
        Console.WriteLine($"{member.Name}是方法");
    }
    if (member is ConstructorInfo)
    {
        Console.WriteLine($"{member.Name}是构造方法");
    }
    if (member is PropertyInfo)
    {
        Console.WriteLine($"{member.Name}是属性");
    }
    if (member is EventInfo)
    {
        Console.WriteLine($"{member.Name}是事件");
    }
}
  • 可以利用TypeInfo的实例方法GetDeclaredXXX返回对应的XXXInfo
  • MethodInfo可以通过GetParameters获得参数信息数组ParameterInfo

调用类型的成员

使用绑定句柄减少内存消耗

  • 原文:许多应用程序都绑定了一组类型(Type 对象)或类型成员(MemeberInfo 派生对象),并将这些对象保存在某种形式的集合中。以后,应用程序搜索这个集合,查找特定对象,然后调用(invoke)这个对象。这样会占用大量的内存,所以FCL定义三个RuntimeTypeHandle,RuntimeFieldHandle 和 RuntimeMethodHandle里面保存了IntPtr
public static void Main()
{
    // RuntimeTypeHandle
    Type type = typeof(string);
    RuntimeTypeHandle typeHandle = Type.GetTypeHandle(type);
    var convertType = Type.GetTypeFromHandle(typeHandle);

    // RuntimeMethodHandle
    MethodInfo methodInfo = type.GetMethod("Compare");
    RuntimeMethodHandle methodHandle = methodInfo.MethodHandle;
    var convertMethod = MethodInfo.GetMethodFromHandle(methodHandle);

    // RuntimeFieldHandle
    FieldInfo fieldInfo = type.GetField("Empty");
    RuntimeFieldHandle runtimeFieldHandle = fieldInfo.FieldHandle;
    var convertField = FieldInfo.GetFieldFromHandle(runtimeFieldHandle);
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值