[.NET][C#]動態載入指定的Class(動態繫結)

前陣子專案內需要抽換原本共用類別庫的功能並引用third party的dll,但不希望改動原本主程式的程式碼,筆記以下兩種:

  • 動態繫結
  • 依賴注入DI(Unity framework)

類別庫與主程式的低耦合可以選用的做法。

 

 

因為是付費的third party套件不好列出來舉例,這邊我們改舉cache的案例,假設專案內有兩個快取(cache)機制選擇,

  • System.Runtime.Caching(Process內)
  • Microsoft.ApplicationServer.Caching(可以跨機器)

每次都是主程式實體化new Runtime或Appfabric類別起來使用cache,由於耦合程度較高(緊密耦合),當想抽換底層library只用其中一種 cache機制時,就會需要改動所有使用到的主程式,此時可以動態決定使用類別class來保持軟體彈性變得很重要。

 

A.動態繫結:

1.首先新增一個類別庫專案,新增一組介面ICache定義: 給主程式入口的介面共有Add/Remove/Get/Update 4個方法

public interface ICache
{
    void Add(string key, object value);
    void Remove(string key);
    Object Get(string key);
    void Update(string key, object value);
}

2.接著在同一個類別庫專案分別撰寫2個Class實作ICache的方法:

RuntimeMemory.cs

class RuntimeMemoryCache : ICache
    {
        private static ObjectCache cache = new MemoryCache("RuntimeMemoryCache");
        public void Add(string key, object value)
        {
            if (value == null) { return; };
            CacheItemPolicy oPolicy = new CacheItemPolicy();
            oPolicy.AbsoluteExpiration = DateTime.Now.AddMinutes(1440);
            cache.Add(key, value, oPolicy, null);
        }
        public void Remove(string key)
        {
            cache.Remove(key, null);
        }
        public object Get(string key)
        {
            return cache.Get(key, null);
        }
        public void Update(string key, object value)
        {
            cache.Set(key, value, null, null);
        }
    }

AppFabricCache.cs

class AppFabricCache : ICache
    {
        private DataCacheFactory factory;
        private DataCache cache;
        public AppFabricCache()
        {
            factory = new DataCacheFactory();
            cache = factory.GetCache("cardcache");
        }
        public void Add(string key, object value)
        {
            if (value == null) { return; };
            cache.Add(key, value);
            cache.ResetObjectTimeout(key,new TimeSpan(365,23,29,59)); 
        }
        public void Remove(string key)
        {
            cache.Remove(key);
        }
        public object Get(string key)
        {
            return cache.Get(key);
        }
        public void Update(string key, object value)
        {
            cache.Put(key, value);
        }

    }

以上第1、2步不管採用動態繫結或是注入都是相同的,寫介面(interface)是很重要的設計

 

3.組態config檔案內容設定要載入的class。

<appSettings>
  <!--<add key="CacheClass" value="(放class的namespace).RuntimeMemoryCache"/>-->
  <add key="CacheClass" value="(放class的namespace).AppFabricCache"/>

</appSettings>

4.主程式引用類別庫,然後依據組態Config參數使用反射動態載入ICache介面的方式:

這樣程式的維護以及程式單元測試變得容易一些。

 

下一篇筆記 採用DI注入的方式來解決動態載入class需求(使用unity framework)

 

參考:

Dynamically loading classes

Unity Framework: How to Instantiate two classes from the same Interface?

Reflection and Dynamic Class Loading 

Resolving Instances of Types Using Unity

Unity IoC container: tips, tricks and dirty hacks