C# 反射實現動態加載程序集


原文: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.編譯運行

reflaction_demo

完整的代碼

 

 

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” 的實體
        }                                       

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM