C#反射實(shí)現(xiàn)插件式開發(fā)的過(guò)程詳解
前言
插件式架構(gòu),一種全新的、開放性的、高擴(kuò)展性的架構(gòu)體系。插件式架構(gòu)設(shè)計(jì)好處很多,把擴(kuò)展功能從框架中剝離出來(lái),降低了框架的復(fù)雜度,讓框架更容易實(shí)現(xiàn)。擴(kuò)展功能與框架以一種很松的方式耦合,兩者在保持接口不變的情況下,可以獨(dú)立變化和發(fā)布?;诓寮O(shè)計(jì)并不神秘,相反它比起一團(tuán)泥的設(shè)計(jì)更簡(jiǎn)單,更容易理解。
項(xiàng)目介紹
書寫4個(gè)插件類庫(kù),分別傳參實(shí)現(xiàn)“加減乘除”運(yùn)算,調(diào)用插件的客戶端采用Winform窗體程序。
目標(biāo)框架: .NET Framework 4.6.1
項(xiàng)目架構(gòu)和窗體布局:

客戶端程序:
- PluginApp:反射調(diào)用插件
插件描述:
- PluginBase:規(guī)范插件的基類,定義抽象類,開發(fā)的插件的類需要繼承此類,代表遵守這個(gè)規(guī)范。
- CustomPlugInA:實(shí)現(xiàn)加法的插件
- CustomPlugInB:實(shí)現(xiàn)減法的插件
- CustomPlugInC:實(shí)現(xiàn)乘法的插件
- CustomPlugInD:實(shí)現(xiàn)除法的插件
代碼實(shí)現(xiàn)
插件基類
/// <summary>
///插件基類
/// </summary>
public abstract class Base
{
/// <summary>
/// 插件名稱
/// </summary>
/// <returns></returns>
public abstract string Name();
/// <summary>
/// 插件描述
/// </summary>
/// <returns></returns>
public abstract string Desc();
/// <summary>
/// 執(zhí)行方法
/// </summary>
/// <param name="param1">參數(shù)1</param>
/// <param name="param2">參數(shù)2</param>
/// <returns></returns>
public abstract string Run(int param1, int param2);
/// <summary>
/// 版本
/// </summary>
public string Version
{
get { return "1.0.0"; }
}
}PlugInA
public class PlugInA: Base
{
public override string Name()
{
return "PlugInA";
}
public override string Desc()
{
return "加法";
}
public override string Run(int param1,int param2)
{
return (param1 + param2) + "";
}
}
}PlugInB
public class PlugInB : Base
{
public override string Name()
{
return "PlugInB";
}
public override string Desc()
{
return "減法";
}
public override string Run(int param1, int param2)
{
return (param1 - param2) + "";
}
}PlugInC
public class PlugInC : Base
{
public override string Name()
{
return "PlugInC";
}
public override string Desc()
{
return "乘法";
}
public override string Run(int param1, int param2)
{
return (param1 * param2) + "";
}
}PlugInD
public class PlugInD : Base
{
public override string Name()
{
return "PlugInD";
}
public override string Desc()
{
return "除法";
}
public override string Run(int param1, int param2)
{
return (param1 / param2) + "";
}
}客戶端核心代碼:
public partial class FrmMain : Form
{
public FrmMain()
{
InitializeComponent();
dgrvPlugins.AutoGenerateColumns = false;
}
List<PluginModel> List = new List<PluginModel>();
readonly string PlugInPath = Application.StartupPath + "\\PlugIns";
/// <summary>
/// 載入插件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btLoadPlugins_Click(object sender, EventArgs e)
{
if (!Directory.Exists(PlugInPath))
{
Directory.CreateDirectory(PlugInPath);
}
List.Clear();
string[] files = Directory.GetFiles(PlugInPath);
foreach (string file in files)
{
if (file.ToLower().EndsWith(".dll"))
{
try
{
Assembly assembly = Assembly.LoadFrom(file);
Type[] types = assembly.GetTypes();
foreach (Type type in types)
{
if (type.BaseType.FullName == "PlugInBase.Base")
{
object obj = assembly.CreateInstance(type.FullName);
string name = type.GetMethod("Name").Invoke(obj, null).ToString();
string desc = type.GetMethod("Desc").Invoke(obj, null).ToString();
string version = type.GetProperty("Version").GetValue(obj).ToString();
List.Add(new PluginModel
{
Name = name,
Desc = desc,
Version = version,
type = type,
Obj = obj
});
}
}
}
catch (Exception ex)
{
throw ex;
}
}
}
dgrvPlugins.DataSource = new BindingList<PluginModel>(List);
}
/// <summary>
/// 打開插件目錄
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btOpenPluginDir_Click(object sender, EventArgs e)
{
Process.Start(PlugInPath);
}
/// <summary>
/// 執(zhí)行選中插件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btExcute_Click(object sender, EventArgs e)
{
//獲取選擇的插件信息
int index = dgrvPlugins.CurrentRow.Index;
object obj = List[index].Obj;
Type type = List[index].type;
//參數(shù)
object[] inParams = new object[2];
inParams[0] =Convert.ToInt32( dgrvPlugins.CurrentRow.Cells[2].Value);
inParams[1] = Convert.ToInt32(dgrvPlugins.CurrentRow.Cells[3].Value);
object value = type.GetMethod("Run").Invoke(obj, inParams);
MessageBox.Show(Convert.ToString(value),"結(jié)果",MessageBoxButtons.OK);
}
}項(xiàng)目配置
插件生成配置
編譯生成項(xiàng)目的時(shí)候需要注意,此處的調(diào)用插件是通過(guò)反射調(diào)用.dll中類和方法,所以首先要找到這個(gè).dll的文件,所以此處我們?cè)赪inform客戶端程序下建立一個(gè)存放類庫(kù)dll的文件 PlugIns ,在插件類庫(kù)項(xiàng)目生成后事件命令中,填入如下命令:
copy /Y "$(TargetDir)$(ProjectName).dll" "$(SolutionDir)\PlugIns"
以上命令代表,在項(xiàng)目的類庫(kù)生成后,將類庫(kù)copy到解決方案的路徑子文件夾 PlugIns ,也就是我們建立存放自定義插件的文件夾。當(dāng)然,如果不怕麻煩,每次生成后,手動(dòng)復(fù)制到此文件夾也可以,直接復(fù)制到客戶端程序的 ..\bin\PlugIns 文件夾下。

插件路徑配置
全選這些類庫(kù),把這些類庫(kù)設(shè)置為"如果較新則復(fù)制",這樣每次在編譯客戶端程序,如果自定義插件有更新,則同步會(huì)復(fù)制到 bin 目錄下

插件基類配置
插件基類提供了規(guī)范,需要在類庫(kù)的生成后事件,添加命令:
copy /Y "$(TargetDir)$(ProjectName).dll" "$(SolutionDir)\bin\Debug"
將生成的dll文件,拷貝到客戶端程序的 bin 路徑下

調(diào)用演示CustomPlugInA

CustomPlugInB

CustomPlugInC

CustomPlugInD

插件開發(fā)優(yōu)缺點(diǎn)
- 把擴(kuò)展功能從框架中剝離出來(lái),降低了框架的復(fù)雜度,讓框架更容易實(shí)現(xiàn)
- 宿主中可以對(duì)各個(gè)模塊解析,完成插件間、插件和主程序間的通信。
- 插件開發(fā)的可擴(kuò)展性,靈活性比較高,而且可以進(jìn)行定制化開發(fā)。
缺點(diǎn)
- 每一個(gè)插件被編譯成了dll,各模塊無(wú)法單獨(dú)運(yùn)行,必須依托于主程序。
- 修改插件時(shí),由于生成的是dll,無(wú)法快速直觀的查看修改以及調(diào)試。
- 每一個(gè)插件必須依賴于某一個(gè)規(guī)范。
到此這篇關(guān)于C#反射實(shí)現(xiàn)插件式開發(fā)的文章就介紹到這了,更多相關(guān)C#反射插件式開發(fā)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
DevExpress實(shí)現(xiàn)GridControl單元格編輯驗(yàn)證的方法
這篇文章主要介紹了DevExpress實(shí)現(xiàn)GridControl單元格編輯驗(yàn)證的方法,很實(shí)用的功能,需要的朋友可以參考下2014-08-08
C#操作LINQ to SQL組件進(jìn)行數(shù)據(jù)庫(kù)建模的基本教程
這篇文章主要介紹了C#操作LINQ to SQL組件進(jìn)行數(shù)據(jù)庫(kù)建模的基本教程,LINQ to SQL被集成在.NET框架之中,需要的朋友可以參考下2016-03-03
C#12中的Collection expressions集合表達(dá)式語(yǔ)法糖詳解
C#12中引入了新的語(yǔ)法糖來(lái)創(chuàng)建常見的集合,并且可以使用..來(lái)解構(gòu)集合,將其內(nèi)聯(lián)到另一個(gè)集合中,下面就跟隨小編一起學(xué)習(xí)一下C#12中這些語(yǔ)法糖的使用吧2023-11-11
C#減少代碼運(yùn)行時(shí)間的7個(gè)實(shí)戰(zhàn)技巧
C#?再次登頂!2025?年?TIOBE?年度編程語(yǔ)言榜單揭曉,C#?摘得桂冠,這已經(jīng)是?C#?三年內(nèi)第二次獲此殊榮,天我們就來(lái)聊聊?7?個(gè)實(shí)戰(zhàn)技巧,讓你的?C#?代碼運(yùn)行時(shí)間大幅縮短2026-04-04
使用C#實(shí)現(xiàn)將Excel轉(zhuǎn)換為Markdown表格
Markdown 表格廣泛應(yīng)用于技術(shù)文檔,README 文件以及各類靜態(tài)站點(diǎn)生成器中,本文將介紹如何使用 C# 將 Excel 文件轉(zhuǎn)換為 Markdown 表格,感興趣的小伙伴可以了解下2026-01-01
基于C#實(shí)現(xiàn)WinForm開發(fā)操作系統(tǒng)的文件管理系統(tǒng)代碼
基于C#的WinForm應(yīng)用程序來(lái)模擬操作系統(tǒng)文件管理系統(tǒng),可以幫助用戶在Windows環(huán)境下進(jìn)行文件的創(chuàng)建、移動(dòng)、刪除與搜索等操作,這種模擬工具有助于學(xué)習(xí)文件系統(tǒng)的工作原理以及測(cè)試和開發(fā)其他軟件項(xiàng)目2024-12-12
C# HttpClient Post參數(shù)同時(shí)上傳文件的實(shí)現(xiàn)
這篇文章主要介紹了C# HttpClient Post參數(shù)同時(shí)上傳文件的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06

