• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

C#反射实现动态加载程序集

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

原文:https://blog.csdn.net/pengdayong77/article/details/47622235

 

在.Net 中,程序集(Assembly)中保存了元数据(MetaData)信息,因此就可以通过分析元数据来获取程序集中的内容,比如类,方法,属性等,这大大方便了在运行时去动态创建实例。

 

 反射提供了封装程序集、模块和类型的对象(Type 类型)。可以使用反射动态创建类型的实例,将类型绑定到现有对象,或从现有对象获取类型并调用其方法或访问其字段和属性。如果代码中使用了属性,可以利用反射对它们进行访问。

主要用途:

  1. 动态加载DLL,实现插件机制。
  2. 实例化DLL中的类型。
  3. 执行后期绑定,访问在运行时创建的类型的方法。

 

 

今天我就介绍下后面的两个用途,其实最初的目的只是想根据配置文件中的值创建对应对象。

Dll

先上一段代码,这是要调用的ClassGreenerycn类,它被编译为DllDemo.dll。

 

    using System;
 
    namespace DllDemo
    {
        public class ClassGreenerycn
        {
            public string Name { get; set; }
            public bool IsTest { get; set; }
            public void Hello()
            {
                Console.WriteLine(Name);
            }
        }
    }

 

很简单的代码,就是一个类中有两个属性,Hello方法会向命令行中输出Name的名称。

 

使用反射创建Dll中的类实例并调用方法

现在再新建一个命令行的工程,该工程就一个用途,动态加载DllDemo.dll,然后实例化一个Name为Greenerycn,IsTest为True的对象,并调用Hello方法。

详细步骤如下:

1.引用反射的命名空间:

using System.Reflection;

2.动态加载Dll

动态加载Dll有3个函数:

public static Assembly Load(string assemblyString);
  • 该方法传入的是Dll的名字,该Dll必须位于全局缓存GAC中才行,不然会报“System.IO.FileLoadException: 未能加载文件或程序集”的异常。
public static Assembly LoadFile(string path);
  • 这个LoadFile最方便,参数就是dll的路径。
public static Assembly LoadFrom(string assemblyFile);
  • 这个方法也可以,参数同样是dll路径。

 

3.获取ClassGreenerycn类的类型

var type = asm.GetType("DllDemo.ClassGreenerycn");

注意,这里需要完整的类型名称,包括签名的命名空间。

4.创建该类型的实例

var instance = asm.CreateInstance("DllDemo.ClassGreenerycn");

5.设置属性

type.GetProperty("Name").SetValue(instance, "http://greenerycn.cnblogs.com", null);
type.GetProperty("IsTest").SetValue(instance, true, null);

6.获取Hello方法

var method = type.GetMethod("Hello");

7.调用Hello方法

method.Invoke(instance, null);

8.编译运行

完整的代码

 

 

using System.Reflection;

namespace ReflectionDllDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            var asm = Assembly.LoadFile(@"d:\3_code\DotNet\DllDemo\DllDemo\bin\Debug\DllDemo.dll");

            var type = asm.GetType("DllDemo.ClassGreenerycn");

            var instance = asm.CreateInstance("DllDemo.ClassGreenerycn");

            type.GetProperty("Name").SetValue(instance, "http://greenerycn.cnblogs.com", null);
            type.GetProperty("IsTest").SetValue(instance, true, null);

            var method = type.GetMethod("Hello");
            method.Invoke(instance, null);
        }
    }
}
---------------------


//在外部动态库和本地类继承同一抽象类AbstractHi并实现同一接口interface 的情况下(甚至接口引用相同实体),主要用于加载不同类名,但实际签名相同的方法的类

//实体
 public class Person
    {
         public string Name {get ;set}
    }
//1.创建接口
    public interface IHi
    {
        string SayHi();
        Person GetPerson();
    }
//2.抽象类继承接口
    public abstract class AbstractHi : IHi
    {
        public abstract string SayHi();
        public abstract Person GetPerson();
    }
-----------------------------------------------
//3.动态库实现(dll文件)
    public class DllDemo : AbstractHi
    {
        public override string SayHi()
        {
            return "Hi";
        }
        public override Person GetPerson()
        {
            var person  =new Person ();
            Person.Name = "MyName";
            return person  ;
        }
    }
------------------------------------------------
//4.加载动态库
        /// <summary>
        /// 返回操作对象,加载类名包含defaultClass字符串的类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="defaultClass"></param>
        /// <returns></returns>
        public static T GetDllDemo<T>(string defaultClass) where T : class
        {
            try
            {
                var asm = Assembly.LoadFile(@"d:\3_code\DotNet\DllDemo\DllDemo\bin\Debug\DllDemo.dll");
                var dllDemo = (from d in asm.DefinedTypes
                    where d.BaseType.FullName.Contains(defaultClass)
                    select d.FullName
                ).FirstOrDefault();
                var type = asm.GetType(dllDemo);
                return Activator.CreateInstance(type) as T;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

//5.实例化
        public class DllDemoBLL
        {
            private AbstractHi_DAL
            public DllDemoBLL()
            {
                _DAL = GetDllDemo<AbstractHi>("DllDemo");
            }
            public string SayHi2()
           {
                return _DAL. SayHi();
            }
           public  Person GetPerson2()
           {
                return _DAL. GetPerson();
            }
        }
//6.调用
        private DllDemoBLL _BLL = new DllDemoBLL();

        public string SayHi3()
        {
            return _BLL.SayHi2();
//最终返回 "Hi"
        }      
   public Person GetPerson3()
        {
            return _BLL.GetPerson2();
//最终返回 Person 属性Name=“MyName” 的实体
        }                                       

 

 

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
c#关闭其它应用程序发布时间:2022-07-10
下一篇:
Equals()和运算符==的重写准则(C#编程指南)发布时间:2022-07-10
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap