Net Core 透過McMaster.NETCore.Plugins動態載入DLL

在過往或最近的開發專案中,
有時也脫離不了會使用到過往的Legacy Code.
原因有可能是時程或者是等等之類的原因.
但如何盡可能的不影響到現行開發的專案去做到有效隔離.
我想.NET Core Plugins提供了不錯的使用方式,又不去影響新的開發專案結構!

在使用情境上,
剛好小弟這陣子在摸索 Net Core,
想到在開發新專案時礙於時程上的限制,需要引用之前開發的功能.
但又不想直接加入參考,原因在於原本的功能中也有相依的套件,去影響到新專案的結構.
故在此做個記事,如有任何建議也請各位前輩不吝嗇的指導.

假設架構情境如下:

如果說實際的專案Oldversion單純的沒任何相依性的套件,
可能直接使用Assembly.LoadFrom會單純許多
如下

var refDllA = Assembly.LoadFrom($"{AppContext.BaseDirectory}OldJsonTostr.dll");

     Type t = refDllA.GetType("OldJsonTostr.Jsonstr");

var methodInfo = t.GetMethod("JsonToStr");

var o = Activator.CreateInstance(t);

var jsonObj = new { name = "Toast", address = "Taipei" };

var meth = methodInfo.MakeGenericMethod(typeof(object));

string reult = (string)meth.Invoke(o, new object[] { jsonObj });

但假設如果在新專案中引用了不同的Json.Net不同的版本,
到時再建置上可能就會出現找不到相依套件或相依版本不一致.

這時候剛好看到有一個方案能解決小弟的問題,
不過此套件依照作者提及目前仍在測試實驗階段中,建議別使用在正式環境中!
所以服用前請三思XD

.NET Core Plugins 

接下來就實作來看看
專案目錄結構如下

程式發布的目錄結構

CorePluginsSample/
    $dlls/
      $OldJsonTostr/
            $OldJsonTostr.dll

在專案中加入Abstractions提供Interface實作各專案中的JsonToStr這個方法
 

namespace Abstractions
{
    public interface Ijsonstr
    {
        string JsonToStr<T>(T p);
    }
}

OldJsonTostr,引用Json.Net Version 8.0.1

using Abstractions;
using Newtonsoft.Json;

namespace OldJsonTostr
{
    public class Jsonstr : Ijsonstr
    {
        public string JsonToStr<T>(T p)
        {
            return JsonConvert.SerializeObject(p);
        }
    }
}

故整體專案結構調整為下圖,
在新專案中CorePluginsSample引用Abstractions內的Inetrface
去呼叫裡面實作的方法

CorePluginsSample 程式碼如下
 

using System;
using System.IO;
using System.Linq;
using Abstractions;
using McMaster.NETCore.Plugins;

namespace CorePluginsSample
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var pluginsDirs = Directory.GetFiles(AppContext.BaseDirectory, "plugin.config", SearchOption.AllDirectories);
            string configPath = pluginsDirs.FirstOrDefault();
            //設定讀取DLL或是設定檔
            var loader = PluginLoader.CreateFromConfigFile(configPath, sharedTypes: new[]
                                                                  {
                                                                            typeof(Ijsonstr),
                                                                 });
            //從PluginLoader取出剛註冊的類別
            var type = loader.LoadDefaultAssembly()
                             .GetTypes()
                             .FirstOrDefault(w => typeof(Ijsonstr).IsAssignableFrom(w));

            var jsonObj = new { name = "Toast", address = "Taipei" };

            var dlls = (Ijsonstr)Activator.CreateInstance(type);

            string result = dlls.JsonToStr(jsonObj);

            Console.WriteLine($"Class Name:{type.Name}{Environment.NewLine} Response Json String :{result}");

            Console.ReadLine();
        }
    }
}

PluginLoader提供了CreateFromAssemblyFile與CreateFromConfigFile 的方法,
一個是直接給予DLL的位置,另一種則是給與設定檔(plugin.config).
至於ShareType則是定義的interface
設定檔格式如下
詳細說明在此

<PluginConfig MainAssembly="OldJsonTostr"/>

接下來看看執行畫面嚕

使用上的總結,作者提供了很方便的方式.
有效的隔離與舊有專案套件引用的相依性問題!
只是作者也開宗明義的說目前還在實驗階段,有些問題尚待克服.

如下圖

希望會有穩定版本可以出現XD~
在此附上原始碼
GitHub連結


 


參考連結:

.NET Core Plugins

DotNetCorePlugins