第 23 章 程序集加载和反射
程序集的加载
Assembly.Load
加载程序集Assembly.LoadFrom
加载指定路径名的程序集,内部原理就是通过GetAssemblyName
获取程序集名,再利用Assembly.Load
来加载,PS:这个路径可以是URL格式的
反射的性能
- 通过字符串来标识类、成员字段、函数等,通过扫描元数据表进行大量的字符串搜索比较
- 通过反射
调用方法
,需要将实参
打包成数组,然后在线程栈解包,检查实参的正确类型,调用者权限等 可以使用一下方法来避免直接调用函数
- 反射的类型派生自
编译时已知类型
,运行时构造反射类型实例,将对他的引用放到基类变量中,然后调用基类方法 - 反射的类型实现
编译是已知接口
,运行时构造反射类型实例,将对他的引用放到基类变量中,然后调用基类方法
反射发现程序集类型
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);
}