大学IT网 - 最懂大学生的IT学习网站! QQ资料交流群:367606806
当前位置:大学IT网 > C#技巧 > 深入理解c#反射

深入理解c#反射

关键词:反射  阅读(662) 赞(18)

[摘要]反射是基于net的组件化编程,而非托管dll是基于不同平台开发普通dll,不具备组件性质,自然不能用反射来获取。

反射:

资料的搜集,代码整理。

反射是基于net的组件化编程,而非托管dll是基于不同平台开发普通dll,不具备组件性质,自然不能用反射来获取。

提供了描述程序集、模块和类型的对象(Type 类型),可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。通过反射可以得到给定程序集所包含的所有类型的列表,列表包括给定类型中定义的方法、字段、属性和事件、给定类支持的借口、方法的参数和其他相关信息如基类、命名空间、数据等

System.Reflection命名空间内的各类型

(0) AppDomain:应用程序域,可以将其理解为一组程序集的逻辑容器
(1) Assembly 通过它可以加载、了解和操纵一个程序集
(2) AssemblyName 通过它可以找到大量隐藏在程序集的身份中的信息,如版本信息、区域信息等
(3) EventInfo 事件的信息
(4) FieldInfo 字段的信息
(5) MethodInfo 方法的信息
(6) ParameterInfo 参数的信息
(7) PropertyInfo 属性的信息
(8) MemberInfo 是抽象基类,为 EventInfo、FieldInfo 、MethodInfo、PropertyInfo等类型定义了公共的行为。
(9) Module 用来访问带有多文件程序集的给定模块

System.Type类 常用的方法和属性

      属性

   Attributes 获取与 Type 关联的属性。
      IsAbstract 获取一个值,通过该值指示 Type 是否为抽象的并且必须被重写。
IsClass 获取一个值,通过该值指示 Type 是否是一个类;即,不是值类型或接口。
      IsInterface获取一个值,通过该值指示 Type 是否为接口(即不是类或值类型)。

      ...........

      方法

      GetEvent (String) 返回表示指定的公共事件的 EventInfo 对象。

      -GetEvent(String, BindingFlags) 当在派生类中重写时,使用指定绑定约束,返回表示指定事件的 EventInfo 对象。

      -GetEvents() 返回由当前 Type 声明或继承的所有公共事件。

      GetMember(String) 搜索具有指定名称的公共成员。-GetMember(String ,BindingFlags) - GetMembers()

      GetMethod(String) 搜索具有指定名称的公共方法。

............

Demo 1:

Assembly sem = Assembly.Load("****命名空间*****"); // Assembly.Load

Type type = sem.GetType("****命名空间.类名******");

object ob = Activator.CreateInstance(type);

MethodInfo mInfo= type.GetMethod("**方法名**");

method.Invoke(ob, null);//执行

Demo 2 :

System.Reflection.Assembly sem = System.Reflection.Assembly.LoadFile(@"path\xxx.dll");

    //Assembly.LoadFile

Type type = sem.GetType("****命名空间.类名******");

object ob = Activator.CreateInstance(type);

MethodInfo mInfo = type.GetMethod("**方法名**");

mInfo.Invoke(ob, new object[] { "wangliuzheng" });

Assembly.Load() Assembly.LoadFrom() Assembly.LoadFile() 之间联系和区别

1,Assembly.Load()

这个方法通过程序集的长名称(包括程序集名,版本信息,语言文化,公钥标记)来加载程序集的,会加载此程序集引用的其他程序集,

一般情况下都应该优先使用 这个方法,他的执行效率比LoadFrom要高很多,而且不会造成重复加载的问题(原因在第2点上说明)

使用这个方法的时候, CLR会应用一定的策略来查找程序集,实际上CLR按如下的顺序来定位程序集:

⑴如果程序集有强名称,在首先在全局程序集缓(GAC)中查找程序集。

⑵如果程序集的强名称没有正确指定或GAC中找不到,那么通过配置文件中的<codebase>元素指定的URL来查找

⑶如果没有指定强名称或是在GAC中找不到,CLR会探测特定的文件夹

2,Assembly.LoadFrom()

这个方法从指定的路径来加载程序集,实际上这个方法被调用的时候,CLR会打开这个文件,获取其中的程序集版本,语言文化,公钥标记等信息,把他们传递给 Load方法,接着,Load方法采用上面的策略来查找程序集。如果找到了程序集,会和LoadFrom方法中指定的路径做比较,如果路径相同,该程序集 会被认为是应用程序的一部分,如果路径不同或Load方法没有找到程序集,那该程序集只是被作为一个“数据文件”来加载,不会被认为是应用程序的一部分。

这就是在第1点中提到的Load方法比LoadFrom方法的执行效率高的原因。另外,由于可能把程序集作为“数据文件”来加载,所以使用 LoadFrom从不同路径加载相同程序集的时候会导致重复加载。当然这个方法会加载此程序集引用的其他程序集。

3,Assembly.LoadFile()

这个方法是从指定的文件来加载程序集,和上面方法的不同之处是这个方法不会加载此程序集引用的其他程序集!

区别

LoadFile 方法用来来加载和检查具有相同标识但位于不同路径中的程序集.但不会加载程序的依赖项 [ LoadFile:加载指定路径上的程序集文件的内容]

LoadFrom 不能用于加载标识相同但路径不同的程序集. [ LoadFrom: 根据程序集的文件名加载程序集文件的内容]

1、Assembly.LoadFile只载入相应的dll文件,比如Assembly.LoadFile("xxx_1.dll"),

则载入xxx_1.dll,xxx_1.dll中引用了xxx_2.dll的话,xxx_2.dll不会被载入。

Assembly.LoadFrom则不一样,它会载入dll文件及其引用的其他dll,比如上面的例子,xxx_2.dll也会被载入。

2、用Assembly.LoadFrom载入一个Assembly时,会先检查前面是否已经载入过相同名字的Assembly,比如xxx.dll有两个版本(版本1在目录1下,版本2放在目录2下),程序一开始时载入了版本1,当使用Assembly.LoadFrom("xx//xxx.dll")载入版本2时,不能载入,而是返回版本1。Assembly.LoadFile的话则不会做这样的检查,比如上面的例子换成Assembly.LoadFile的话,则能正确载入版本2。



相关评论