?j 生曲解迓方劉B )
F6
Alt+Fll
∣? 生成 WainIo (U) Shift+F6
快速实现接口
PUklIiC Ilyf Iug' : ιl ∣' aιnΞO r PUbIXC class Inyr LUg :
* I
}
实现接口 JMdinlCT (D
显式豹IS 口 "ιMainIQ j, (X)
插件同时也可以继承其他类,但插件名称必须写在后面,例如:
P >ublic decimal Mathl (decimal a j decimal t ∣) [ throV nev NotIIn-PI eaerιt e d_Ex C ept LOIL (): }
}
PUtl 丄:Lc class IIlyF IUg : IMalnIU
PULliC class IltyP l lIIg :F□ rιn3 iMainlO
{ ,
PUhIiC decimal Math(de Ginal ? decimal b) {
return a ÷t∣:
//this. SlioiirDiale^O :可次冒接惟用J?m
项目引用DLL
常夬方奚蜃源普理器和EgWgWτ ? X
? b -
EJl解:莫方案"MainlO"卫八垓口1
J回MainIo
b N Prcpertiss
Z滚?α弓用(R)?“
制酿务引用⑸小
I苗管理NUGet程序包IML,
F競为此范围⑸
[fi]新建鬆方垃源苣更器胆鈕NJ 輯丢方養資谆貫坦蛊团认負Sg肓埋赛
氐却乃fctlB:i??U) ?UJM SQLQ;ZJ Fr?≠qι.qr~l> .
MN fI ?
S?L M ?jtl?∏Λ*?er?t:
.qe? FnTnE.
IV fl
賞rT∏r-?j
LiJL』L KdlJlζJDd
以下正文
追寅■?τ?∑7
z,∣e?≡-rita≥icr FgrtflEnDi l lL 匚
i l?Jh?g.S∣∣
∣?
M>P∣u?iπldll
r*i?
≈∣rγn∣ug?i d∣
∣
PrwertotC!*-Fra H∏^≡σrk LUna
^rei≠r*i!,?ΛΓff Newark Rαy?le
43
ΛO.OD
4MJD
c4?>.G
接口的作用是定义一个规则,让插件和程序按这个规则来开发。规则可以是函数、属性… 简单定义
,本文一个带返回值及参数的接口:
并生成DLL
USing System;
USing SyStem.CollectiOns.Generic;
USing SyStem.Text;
n amespace MainIo
PUbIiC in terface iMai nlO
{
DeCimaI Math( DeCimaI a, DeCimaI b);
}
三、插件
新建类库,写一个类,并继承接口,具体的写法为:
获取指定文件夹内所有文件的路径名称==》筛选出“ .DLL” ==》实例化“ DLL”(就是把DLL变成类库)==》类库里面寻找有没有指定接口的类==》加载到ArraryLiSt里面去,这样我们的得到了一个具有约定接口的类
了,剩下的就是调用类里面的东西了。简单一点的说就是:
调用方法有两种实现方式:
第一:in Voke
接上面加载的过程,我们已经得到了一个类,我们通过这个类就可以调用里面的方法了,具步骤就是
:类==》查找指定方法==》invoke实例化并执行
这个方法不需要程序加载接口的DLL,但必须把接口的DLL放在和插件DLL同一个文件下
第二:强制转换
加载接口的dll到程序里面,而后用强制类型转换,然后就可以直接调用方法了
((接口的类型)ArrayLiSt里面的对象).函数(参数…)
这种做法要求assmebly 在加载Dll的时候,必须用LOadFiIe而不能用LOadFrOm
下面直接上代码:程序界面设计
重点的代码都加粗了
USing System;
USing SySte m.IO;
USing SyStem.Reflection;//实例化aessmbly
USing SyStem.Collectio ns;//arraylist
USi ng Ma in 10; // 接口的类库
n amespace主程序
{
PUbIiC PartiaI class Form1 : Form
PUbIiC Form1()
ArrayLiSt PIUgLiSt = new ArrayList ();//用来存放类的容器
PriVate void BtnLoad_Click( ObjeCt Sender, EVentArgs e)
String[] Files = DireCtOry .GetFiles(Application .StartupPath +@"\plug");
〃获取指定文件夹内所有文件完整路径,手动在debug下面添加文件夹plug
ASSemblyab = AssembIyLoadFiIe(FiIe);
〃文件加载,此处如果用LOadFrOm,则无法实现方法强制转换类型的方法调用,只能用invoke
Type[] ts = ab.GetTypes();
〃类集合的获取,一个类库里面可以有多个namespace 一个namespacei面可以有多个class (类)
foreach (TyPe t in ts)
{
if (t.GetInterface("iMainIO" ) != null)
//类筛选,在每个类里面用GetI nterface :搜索具有指定名称的接口
{
PIUgLiStAdd(ab.Createlnstance(t.FuIIName));// 类加载到容器里面
IistBox1.ltems.Add(t.FuIIName); //显示在Iistbox1 中
DeCimal a = Con VertTODeCimal(txtP1.Text);
DeCimaI b = Con VertTODeCimal(txtP2.Text);
IabReSUltTeXt = ((iMainlO )plugList[listBox1.Selectedlndex]).Math(a, b).ToString();
〃主程序必须引用接口的类库
〃强制将加载的类转换为接口的类型--就是我们开始定义接口那个类型,而后就可以直接xx.类.函数(参数…)
PriVate void BtnCall2 Click( ObjeCt Sender, EVentArgs e) {
if (IiStBox1.Selected In dex == -1) retur n;
try
{
DeCimaI a = Con VertTODeCimal(txtP1.Text);
DeCimaI b = Con vert.ToDecimal(txtP2.Text);
ObjeCt obj = PIUgLiSt[listBox1.SelectedIndex]// 把加载到的对象赋值给一个基类
IabReSUlt.Text = obj.GetType().GetMethod( "Math" ).Invoke(obj, new ObjeCt[] { a, b }).ToString();
/∕getType,获取基类的具体类型,然后在这个类型里面查找具体的方法撚后用invoke实例化
〃所有的参数用ObjeCt[]的方式赋值,具体为new ObjeCt[] {参数1,参数2,参数3,参数……} }
CatCh (EXCePti on ex)
{