程序集加载

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

还有一个Assembly.LoadFrom方法加载指定路径名的程序集,实际上其内部是先通过AssemblyName.GetAssemblyName获取AssemblyName对象,然后调用Assembly.Load方法。

此时load方法会在各个位置(前面03章讲过)查找程序集,如果已经加载了此程序集就返回已加载的程序集,如果没有加载就去加载找到的程序集,如果没有找到,就加载路径所给的那个程序集。(所以很清楚了解到不一定会加载所指定的那个程序集,而可能是另一个。在这里如果每次生成强命名程序集时更新版本号,才会使LoadFrom方法的行为符合预期)

LoadFrom方法允许传递一个Url作为实参,CLR会下载文件,把它安装到用户的下载缓存中,再从那儿加载文件。

ReflectionOnlyLoadFrom函数也可以加载程序集,且禁止程序集中的任何代码执行。

使用反射构建动态可扩展应用程序

既然加载了程序集,那么就应该要有办法去使用程序集中定义的类,这种办法就是反射。

利用System.Reflection命名空间中包含的类型,可以写代码来反射元数据表,为所加载的程序集中所包含的元数据提供对象模型。

反射一些例子:

首先先建立一个用于反射的程序集,代码如下:

namespace HelloWorld
{
public class Man
{
public string _name;
public Man(String name) {
this._name = name;
}
public void ShowName() {
Console.WriteLine(this._name);
}
}
} namespace HelloWorld
{
public class Troy:Man
{
private string _jobName;
public Troy(string name,string jobName):base(name) {
this._jobName = jobName;
}
public void ShowJobName() {
Console.WriteLine(this._jobName);
}
}
}

然后生成了一个叫HelloWorld.dll的文件,然后开始玩反射

      //首先加载程序集,获取程序集对象
Assembly myAssembly=Assembly.LoadFrom("D:\\HelloWorld.dll");
//玩程序集中定义的公共类型
foreach (Type type in myAssembly.ExportedTypes) {
//打印类型全名
Console.WriteLine("类型全名:"+type.FullName);
Console.WriteLine(type.FullName + "的基类:" + type.BaseType.FullName);
//判定类型是否为String(当然这是不可能的,因为只有Man和Troy)
if (type == typeof(String)) {
Console.WriteLine("有个String类型");
}
//Type对象是轻量型的类型引用,更全面的信息在TypeInfo对象(获取TypeInfo对象会强迫CLR确保已加载类型的定义程序集,从而对类型进行解析。(代价高昂)),
//如下转换
TypeInfo typeInfo = IntrospectionExtensions.GetTypeInfo(type);
//也可以反着转
Type tmpType = typeInfo.AsType();
//泛型类型的Type
Type openType = typeof(Dictionary<,>);//开放类型
Type closedType= openType.MakeGenericType(typeof(int), type);//闭合类型
//实例化
Object obj= Activator.CreateInstance(closedType);
Console.WriteLine(obj.GetType());
}

反射的性能

反射是相当强大的机制,但是也有其缺点:

  • 反射造成编译时无法保证类型安全性,因为它是在运行时才依靠字符串来对类进行实例化等操作。
  • 反射的速度很慢,因为是在运行时靠字符串去标识成员,发现它们,使用它们。整个过程中都是用字符串来搜索。

设计支持加载项的应用程序

构建可扩展应用程序时,一般使用接口而不是基类,因为接口允许加载项开发人员选择自己的基类。

为宿主接口类的方法定义参数和返回类时,尝试使用MSCorLib.dll定义的接口和类型。因为CLR只加载一个MSCorLib.dl,所以不会出现类型版本不匹配的情况,且有助于减少应用程序对内存的需求。

反射与类型的成员

System.Reflection.MemberInfo封装了所有类型成员都通用的一组属性。它的一些派生类如MethodInfo则封装了与特定类型成员相关的更多属性。

直接上代码简单易懂:

class Program
{
static void Main(string[] args)
{
Type type = typeof(Troy);
Object obj = Activator.CreateInstance(type);
MethodInfo[] arrMethod= type.GetMethods();
foreach (var methodInfo in arrMethod) {
if (methodInfo.GetParameters().Length == )
{
methodInfo.Invoke(obj, null);
}
}
Console.Read();
} }
public class Troy{
public string name;
public Troy() {
name = "Troy";
}
public void Show() {
Console.WriteLine(name);
}
}

对于FieldInfo(字段)和PropertyInfo(属性)可以用GetValue和SetValue来获取和设置实例的值,

对于MethodInfo(方法)和ConstructorInfo(构造器)则可以用Invoke来调用,

对于EventInfo(事件)可以用AddEventHandler和RemoveHandler来增加事件回调函数和减少回调函数。

上述方法其实很麻烦,如果用dynamic方法那么就会和一般的写程序一样简单了。

【C#进阶系列】23 程序集加载和反射的更多相关文章

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

    查看,clr via c# 程序集加载和反射(1) 8,发现类型的成员: 字段,构造器,方法,属性,事件,嵌套类型都可以作为类型成员.其包含在抽象类MemberInfo中,封装了所有类型都有的一组属性 ...

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

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

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

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

  4. 老调重弹:JDBC系列之<驱动加载原理全面解析) ----转

      最近在研究Mybatis框架,由于该框架基于JDBC,想要很好地理解和学习Mybatis,必须要对JDBC有较深入的了解.所以便把JDBC 这个东东翻出来,好好总结一番,作为自己的笔记,也是给读者 ...

  5. RX系列四 | RxAndroid | 加载图片 | 提交表单

    RX系列四 | RxAndroid | 加载图片 | 提交表单 说实话,学RxJava就是为了我们在Android中运用的更加顺手一点,也就是RxAndroid,我们还是先一步步来,学会怎么去用的比较 ...

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

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

  7. CLR中的程序集加载

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

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

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

  9. 【iOS系列】-UIWebView加载网页禁止左右滑动

    [iOS系列]-UIWebView加载网页禁止左右滑动 问题: 做项目时候,用UIWebView加载网页的时候,要求是和微信网页中打开的网页的效果一样,也即是只能上下滑动,不能左右滑动,也不能缩放. ...

随机推荐

  1. 每周一书-《鸟哥的Linux私房菜基础学习篇(第四版)》台湾原版,你想要吗?

     首先说明,本周活动有效时间为2016年10月19日到2016年10月31日.   目在介绍这本书之前,首先要感谢QQ号为:1084830483(路在远方),来自哈尔滨工程大学的同学赠送给玄魂工作室的 ...

  2. 纯命令行的编辑利器:用好 awk 与 sed

    awk 的基本语法 awk 是模式查找与处理语言,是文本处理的利器.使用 awk 可以只用一条简单的命令完成复杂的文本数据处理. awk 命令的基本结构为: awk '模式 {处理}' 文件 比如,打 ...

  3. lua中清空目录和递归创建目录

    lua中的 lfs.mkdir lfs.rmdir只能针对单个目录,且lfs.rmdir不能清空文件夹 于是我想到了使用os.execute 递归创建目录如下os.execute("mkdi ...

  4. ubuntu升级内核后vmware-player启动失败

    在虚拟机软件中,vmware player是对硬件支持很好的,通过它可以很方便的使用网银.单片机开发等等工作.但是最近ubuntu每次升级内核后,vmware都会启动失败,提示:Before you ...

  5. Step by step Dynamics CRM 2011升级到Dynamics CRM 2013

    原创地址:http://www.cnblogs.com/jfzhu/p/4018153.html 转载请注明出处 (一)检查Customizations 从2011升级到2013有一些legacy f ...

  6. C语言 · 回文数 · 基础练习

    问题描述 1221是一个非常特殊的数,它从左边读和从右边读是一样的,编程求所有这样的四位十进制数. 输出格式 按从小到大的顺序输出满足条件的四位十进制数.   代码如下: 注意:这里要提醒一下读者:蓝 ...

  7. sublime text3同时编辑多行

    sublime text3同时编辑多行 下面的才是正确的姿势,之前一直是shift + 右键 拖啊. http://stackoverflow.com/questions/32127604/how-t ...

  8. IL指令汇总

    名称 说明   名称 说明 Add 将两个值相加并将结果推送到计算堆栈上.   Ldelem.I1 将位于指定数组索引处的 int8 类型的元素作为 int32 加载到计算堆栈的顶部. Add.Ovf ...

  9. 单页面实现之hash

    至学了angularJs后,发现这个单页面应用不知道在没有angularJs的情况下怎么实现. 所以就此对这个思考与资料并行,终于知道这个的实现基本原理. 首先angularJs的实现是hash值的变 ...

  10. sizzle分析记录: 自定义伪类选择器

    可见性 :hidden :visible 隐藏对象没有宽高,前提是用display:none处理的 jQuery.expr.filters.hidden = function( elem ) { // ...