C#反射-Assembly.Load、LoadFrom与LoadFile

反射Demo:html

public class Person
{
    public int Age;


    public void SayHello()
    {
        Console.WriteLine("Hello Person");
    }
}
class Program
{
    static void Main(string[] args)
    {
        //把程序集像读取文件同样读取出来,动态的调用程序集里面的方法
        Person p = new Person();
        /*
         * 使用Type描述类型特征
            Type t1=typeof(ClassName);
            Type t2=ClassName.GetType();

            t1.GetEvents/t1.GetFields/
            t1.GetMembers
            t1.GetMethods() //返回全部公共方法
         */
        Type t1 = typeof(Person);
        Type t2 = p.GetType();

        //GetEvents 获取全部的事件
        EventInfo[] events = t1.GetEvents();
        foreach (var item in events)
        {
            Console.WriteLine("Event: " + item.Name);
        }
        //GetFields 获取全部的public字段
        FieldInfo[] fields = t1.GetFields();
        foreach (var item in fields)
        {
            Console.WriteLine("Fields: " + item.Name);
        }
        //GetMethods 获取全部的方法
        MethodInfo[] methods = t1.GetMethods();
        foreach (var item in methods)
        {
            Console.WriteLine("Method: " + item.Name);
        }
        Console.ReadKey();
    }
}

反射:【从文件中读取程序集中的成员,并使用它】函数

->实现步骤:spa

->使用Assembly.LoadFrom(文件名全名)  【得到程序集对象Assembly】设计

->使用GetTypes()得到全部的类型信息(Type对象) 【读取类型 GetType】code

->Activator.CreateInstance(Type类型的数据)建立指定类型的对象  【建立对象 Activator.CreateInstance】//实例.方法()htm

->若是须要调用方法,使用<type>.GetMethod(方法名)得到MethodInfo类型对象 【得到方法 <type>.GetMethod】对象

->调用 方法对象.Innvoke(实例,参数);blog

//DrHao 类库事件

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DrHao
{
    public class Hao
    {
        public void Fun1()
        {
            Console.WriteLine("我是没有参数的Fun1");
        }

        public void Fun1(int num1)
        {
            Console.WriteLine("参数是:" + num1);
        }

        public int Fun1(int num1, int num2)
        {
            return num1 + num2;
        }

        private void Func()
        {
            Console.WriteLine("无参数的私有方法");
        }
    }
}

//Main函数get

class Program
{
    static void Main(string[] args)
    {
        //把程序集像读取文件同样读取出来,动态的调用程序集里面的方法

        //反射
        //读取程序集
        Assembly asm = Assembly.LoadFrom(@"E:\Program2013\20160416_Reflect\DrHao\bin\Debug\DrHao.dll");
        //读取类型
        Type t = asm.GetType("DrHao.Hao");
        //建立对象信息
        object o = Activator.CreateInstance(t);
        //得到方法
        ////私有方法
        //MethodInfo method = t.GetMethod("Func", BindingFlags.Instance|BindingFlags.NonPublic);

        MethodInfo method = t.GetMethod("Fun1", new Type[] { typeof(int), typeof(int) });

        object result = method.Invoke(o, new object[] { 123, 456 });
        Console.WriteLine("|{0}|", result);
        Console.ReadKey();
    }
}

关于.NET中的反射,经常使用的有三个方法:

Assembly.Load()

Assembly.LoadFrom()

Assembly.LoadFile()

1. Assembly.Load() 

Load()方法接收一个String或AssemblyName类型做为参数,这个参数其实是须要加载的程序集的强名称(名称,版本,语言,公钥标记)。

例如.NET 2.0中的FileIOPermission类,它的强名称是:

System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

对于弱命名的程序集,则只会有程序集名称,而不会有版本,语言和公钥标记。如 TestClassLibrary

2. Assembly.LoadFrom()

LoadFrom()方法能够从指定文件中加载程序集,经过查找程序集的AssemblyRef元数据表,得知全部引用和须要的程序集,而后在内部调用Load()方法进行加载

Assembly.LoadFrom(@"C:\ABC\Test.dll");

3. Assembly.LoadFile()

LoadFile()从一个指定文件中加载程序集,它和LoadFrom()的不一样之处在于LoadFile()不会加载目标程序集所引用和依赖的其余程序集

您须要本身控制并显示加载全部依赖的程序集

Assembly.Load()方法,Assembly.LoadFrom()方法,Assembly.LoadFile()方法的区别!

1:Assembly.Load()

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

通常状况下都应该优先使用 这个方法,他的执行效率比LoadFrom要高不少,并且不会形成重复加载的问题(缘由在第2点上说明)

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

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

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

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

假设你的应用程序目录是C:\AppDir,<probing>元素中的privatePath指定了一个路径Path1,你要定位的程序集是AssemblyName.dll则CLR将按照以下顺序定位程序集

  C:\AppDir\AssemblyName.dll

  C:\AppDir\AssemblyName\AssemblyName.dll

  C:\AppDir\Path1\AssemblyName.dll

  C:\AppDir\Path1\AssemblyName\AssemblyName.dll

若是以上方法不能找到程序集,会发生编译错误,若是是动态加载程序集,会在运行时抛出异常!

2:Assembly.LoadFrom()

这个方法从指定的路径来加载程序集,实际上这个方法被调用的时候,CLR会打开这个文件,获取其中的程序集版本,语言文化,公钥标记等信息,把他们传递给 Load方法,

接着,Load方法采用上面的策略来查找程序集。若是找到了程序集,会和LoadFrom方法中指定的路径作比较,若是路径相同,该程序集会被认为是应用程序的一部分,

若是路径不一样或Load方法没有找到程序集,那该程序集只是被做为一个“数据文件”来加载,不会被认为是应用程序的一部分。

这就是在第1点中提到的Load方法比LoadFrom方法的执行效率高的缘由。

另外,因为可能把程序集做为“数据文件”来加载,因此使用 LoadFrom从不一样路径加载相同程序集的时候会致使重复加载。固然这个方法会加载此程序集引用的其余程序集。

3:Assembly.LoadFile()

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

结论:通常你们应该优先选择Load方法来加载程序集,若是遇到须要使用LoadFrom方法的时候,最好改变设计而用Load方法来代替!

另:Assembly.LoadFile 与 Assembly.LoadFrom的区别

一、Assembly.LoadFile只载入相应的dll文件,好比Assembly.LoadFile("abc.dll"),则载入abc.dll,假如abc.dll中引用了def.dll的话,def.dll并不会被载入。

Assembly.LoadFrom则不同,它会载入dll文件及其引用的其余dll,好比上面的例子,def.dll也会被载入

二、用Assembly.LoadFrom载入一个Assembly时,会先检查前面是否已经载入过相同名字的Assembly,好比abc.dll有两个版本(版本1在目录1下,版本2放在目录2下),

程序一开始时载入了版本1,当使用Assembly.LoadFrom("2\\abc.dll")载入版本2时,不能载入,而是返回版本1。

Assembly.LoadFile的话则不会作这样的检查,好比上面的例子换成Assembly.LoadFile的话,则能正确载入版本2。

LoadFile:加载指定路径上的程序集文件的内容。LoadFrom: 根据程序集的文件名加载程序集文件的内容。

区别:

LoadFile 方法用来来加载和检查具备相同标识但位于不一样路径中的程序集.但不会加载程序的依赖项。

LoadFrom 不能用于加载标识相同但路径不一样的程序集。

参考资料:http://www.cnblogs.com/zagelover/articles/2726034.html

相关文章
相关标签/搜索