程序集加载

程序集加载,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. mina框架详解

     转:http://blog.csdn.net/w13770269691/article/details/8614584 mina框架详解 分类: web2013-02-26 17:13 12651人 ...

  2. 如何让你的JavaScript代码更加语义化

    语义化这个词在 HTML 中用的比较多,即根据内容的结构化选择合适的标签.其作用不容小觑: 赋予标签含义,让代码结构更加清晰,虽然我们可以在标签上添加 class 来标识,但这种通过属性来表示本体的形 ...

  3. java中文乱码解决之道(三)-----编码详情:伟大的创想---Unicode编码

    随着计算机的发展.普及,世界各国为了适应本国的语言和字符都会自己设计一套自己的编码风格,正是由于这种乱,导致存在很多种编码方式,以至于同一个二进制数字可能会被解释成不同的符号.为了解决这种不兼容的问题 ...

  4. 基于GIS的旅游辐射区人口统计

    在旅游规划中,考虑旅游景点周边的人口负载量是很重要的一个方面,这将直接影响资源的投入和配置,开发潜力和规模等.基于GIS可以将人口信息进行空间化的展示,还可以通过空间分析的方法计算出旅游景点辐射区的人 ...

  5. Rabbitmq安装与配置

    install: 1.安装Erlang: $yum -y install erlang 2.安装rabbitmq-server: $rpm --import https://www.rabbitmq. ...

  6. JS原生第六篇 (帅哥)

    复习 按钮不可用    disabled =  "disabled"  ||  true setTimeout   只执行一次    setInterval  执行很多次 递归调用 ...

  7. lua解释执行脚本流程

    #include "lua.hpp" #include <iostream> using namespace std; #pragma comment(lib, &qu ...

  8. 深入理解javascript对象系列第一篇——初识对象

    × 目录 [1]定义 [2]创建 [3]组成[4]引用[5]方法 前面的话 javascript中的难点是函数.对象和继承,前面已经介绍过函数系列.从本系列开始介绍对象部分,本文是该系列的第一篇——初 ...

  9. 通过HTTP协议上传文件

         HTTP是很常见的协议,虽然用得很多,但对细节的了解却是很浅,这回通过向服务端上传文件信息来理解细节.网络库的选择:1.WinHTTP是windows下常用的库:2.CURL是广受喜爱的开源 ...

  10. Util应用程序框架公共操作类(八):Lambda表达式公共操作类(二)

    前面介绍了查询的基础扩展,下面准备给大家介绍一些有用的查询封装手法,比如对日期范围查询,数值范围查询的封装等,为了支持这些功能,需要增强公共操作类. Lambda表达式公共操作类,我在前面已经简单介绍 ...