在過往或最近的開發專案中,
有時也脫離不了會使用到過往的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連結