C#实现插件式开发(超简单傻瓜式教程)

C#实现插件式开发(超简单傻瓜式教程)
C#实现插件式开发(超简单傻瓜式教程)

C#实现插件式开发(超简单傻瓜式教程) 为什么要用插件就不说了,本教程可以实现程序动态加载外部 DLL ,并调用DLL 里面的类、方法, 本教程力求已最简单的方式介绍,减少一些不必要的代码给小白造成混淆。

程序分三个部分:接口、插件、 Windows 程序,比较复杂的是程序如何动态加载与内容调用。

一、正式教程前科普一下基础知识:(非小白点我跳过)

Jlbj 英库 Vi^aI C#

写完代码后shift+f6 生成DLL

生咸冏潟试(D) HRM SQL(

?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)

{

相关主题
相关文档
最新文档