天天躁日日躁狠狠躁AV麻豆-天天躁人人躁人人躁狂躁-天天澡夜夜澡人人澡-天天影视香色欲综合网-国产成人女人在线视频观看-国产成人女人视频在线观看

.NET動(dòng)態(tài)調(diào)用DLL的方法

  很多軟件都是可插拔的,最知名的便是微軟的Windows操作系統(tǒng)。你可以在Windows操作系統(tǒng)上安裝QQ,也可卸掉QQ,這便是可插拔。這里不談Windows的實(shí)現(xiàn),因?yàn)樘^(guò)復(fù)雜。本文就談?wù)劰芾碥浖目刹灏蔚膶?shí)現(xiàn)。相對(duì)Windows操作系統(tǒng),QQ就是它的一個(gè)插件。所以可以簡(jiǎn)單的將開(kāi)發(fā)可插拔的軟件分為兩個(gè)部分。一個(gè)是主應(yīng)用程序的開(kāi)發(fā),一個(gè)是插件的開(kāi)發(fā)。

  比Windows小的,常見(jiàn)的可插拔的軟件是MSN。MSN主應(yīng)用程序由MS開(kāi)發(fā),還存在一些MSN插件開(kāi)發(fā)商,國(guó)內(nèi)好像也有不少,這些插件開(kāi)發(fā)商通過(guò)在插件中植入廣告獲取利潤(rùn)。MS不可能提高源代碼給這些開(kāi)發(fā)商,那么MSN的主應(yīng)用程序和MSN的插件是如何銜接起來(lái)的呢。我想應(yīng)該是MS提供了一些接口和方法供開(kāi)發(fā)商使用,估計(jì)有個(gè)api之類(lèi)的東西,所以開(kāi)發(fā)可插拔的應(yīng)用系統(tǒng)分為三個(gè)部分。

  1、主應(yīng)用程序的開(kāi)發(fā)

  2、公用接口的開(kāi)發(fā)

  3、插件的開(kāi)發(fā)

  了解了這些以后,下面通過(guò)一個(gè)實(shí)例來(lái)說(shuō)明。這個(gè)實(shí)例的原則是可擴(kuò)展性強(qiáng),能向下兼用。

  業(yè)務(wù)需求是:老系統(tǒng)每當(dāng)逢年過(guò)節(jié)的時(shí)候,會(huì)通過(guò)郵件給用戶發(fā)送一些祝福的郵件。現(xiàn)在流行手機(jī)和MSN(QQ沒(méi)有借口)之后,客戶希望系統(tǒng)能通過(guò)手機(jī)短信和MSN的消息給用戶送去祝福。現(xiàn)在我們需要開(kāi)發(fā)手機(jī)短信和MSN留言兩個(gè)插件,然后將它們安裝到系統(tǒng)中去。

  實(shí)現(xiàn):

  為了簡(jiǎn)單起見(jiàn),這里使用控制臺(tái)應(yīng)用程序,如果你有興趣,可以修改成ASP.NET或者Windows Form的。

  定義兩個(gè)接口:

public interface IPluginHost
{
void AddMenuItem(string name, MenuItemClickedHandler clickHandler);
void RegisterComponent<T>(T component) where T : class;
void MailNotice(string messaage);
}
public delegate void MenuItemClickedHandler(string name);

  這個(gè)接口是主應(yīng)用程序繼承的,現(xiàn)在只有MailNotice功能, AddMenuItem是供插件調(diào)用的方法,創(chuàng)建一個(gè)菜單。RegisterComponent是插件向主應(yīng)用程序提供一些方法。

public interface IPlugin
{
void Initialize(IPluginHost pluginHost);
void DoSomething();
}

  上面是插件的接口。

  在主應(yīng)用程序中有一個(gè)加載插件的地方。這里的插件是dll,所以我通過(guò)反射去加載這些dll。

public void LoadPlugin()
{
foreach (string fileName in Directory.GetFiles(Directory.GetCurrentDirectory() + "http://" + "Plugins", "*.dll"))
{
Assembly assembly = Assembly.LoadFile(fileName);
foreach (Type pluginType in assembly.GetTypes())
{
if (!pluginType.IsPublic || pluginType.IsAbstract || pluginType.IsInterface)
continue;
Type concreteType = pluginType.GetInterface(typeof(IPlugin).FullName, true);

if (concreteType != null)
{
IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType);
plugin.Initialize(this);
pluginList.Add(plugin);
break;
}
}
}
}

  主應(yīng)用程序執(zhí)行的代碼如下:

void Start()
{
//郵件發(fā)送祝福
MailNotice("中秋快樂(lè)");
//加載插件
LoadPlugin();
//運(yùn)行插件
if (pluginList.Count > 0)
{
foreach (IPlugin plugin in pluginList)
{
plugin.DoSomething();
}
}

Console.ReadLine();
}

  運(yùn)行結(jié)果如下:

hhqqqq

  開(kāi)發(fā)兩個(gè)插件,都繼承IPlugin。

  手機(jī)短信通知插件:

public class PluginA : IPlugin
{

public void Initialize(IPluginHost pluginHost)
{
IPluginHost myApplication = (IPluginHost)pluginHost;
myApplication.AddMenuItem("Click me", OnClick);

}
private void OnClick(string name)
{
Console.WriteLine("Omg! You clicked me!");
}

public void DoSomething()
{
Console.WriteLine("手機(jī)短信通知:中秋快樂(lè)");
}

}

  MSN通知插件:

public class PluginB : IPlugin
{

public void Initialize(IPluginHost pluginHost)
{
IPluginHost myApplication = (IPluginHost)pluginHost;
myApplication.AddMenuItem("Click me", OnClick);

}
private void OnClick(string name)
{
Console.WriteLine("Omg! You clicked me!");
}

public void DoSomething()
{
Console.WriteLine("MSN信息通知:中秋快樂(lè)");
}

}

  插件的目錄如下圖:

kkkyyy

  運(yùn)行效果:

kkk444

  擴(kuò)展性和兼容性:

  如果我想在主應(yīng)用程序中添加一個(gè)ShowMessageBox方法。而且這個(gè)方法供插件調(diào)用。考慮到版本的兼容性,公開(kāi)的接口是不能修改的。比如:將主應(yīng)用程序的接口修改成:

public interface IPluginHost
{
void AddMenuItem(string name, MenuItemClickedHandler clickHandler);
void RegisterComponent<T>(T component) where T : class;
T GetComponent<T>() where T : class;
void MailNotice(string messaage);
void ShowMessageBox(string message);
}

  那么如何實(shí)現(xiàn)呢,很簡(jiǎn)單,使用依賴注入的方式。添加下面接口:

public interface IMessageBoxHost
{
void ShowMessageBox(string message);
}

  通過(guò)主應(yīng)用程序的構(gòu)造函數(shù),將MessageBoxHost對(duì)下崗注入到主應(yīng)用程序,在通過(guò)插件的構(gòu)造函數(shù),將其注入插件之中。

  主應(yīng)用程序的構(gòu)造函數(shù):

public Program(IMessageBoxHost messageBoxHostInstance)
{
this.messageBoxHostInstance = messageBoxHostInstance;
}

  插件構(gòu)造函數(shù):

public PluginA(IMessageBoxHost messageBoxHost)
{
this.messageBoxHost = messageBoxHost;
}

  修改實(shí)例化插件的代碼:

IPlugin plugin = (IPlugin)Activator.CreateInstance(pluginType, new object[] { messageBoxHostInstance });

  這樣我們對(duì)版本兼容有了保障。

  總結(jié):本文閑談了可插拔應(yīng)用程序的開(kāi)發(fā)原理,文章的后面提供了插件和應(yīng)用程序之間版本兼容的一種方案。有討論才有進(jìn)步,歡迎各位留言。

  參考:A Flexible Plugin System    A more extensible way to build plugin system

NET技術(shù).NET動(dòng)態(tài)調(diào)用DLL的方法,轉(zhuǎn)載需保留來(lái)源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 日本吃孕妇奶水免费观看 | 欧美xxxxx18| 亚洲精品久久久WWW游戏好玩 | 午夜日本大胆裸艺术 | 日本久久网站 | 亚洲国产果果在线播放在线 | 99在线精品国自产拍不卡 | 最新快播网站 | 欧美人禽Zozo动人物杂交 | 不卡无线在一二三区 | 欧美精品AV精品一区视频 | 在线视频一区二区三区在线播放 | 翁熄性放纵交换300章 | 国产亚洲精品久久久久小 | 99精品无码AV在线播放 | 国产喷水1区2区3区咪咪爱AV | 久久国产免费一区二区三区 | 免费A级毛片无码无遮挡内射 | 亚洲 欧美 国产 在线 日韩 | 大香伊蕉在人线国产97 | 九九精品国产亚洲A片无码 九九精彩视频在线观看视频 | 女人高潮时一吸一夹 | 高清日本片免费观看 | 我们中文在线观看免费完整版 | 99热只有精品| 国产午夜精品一区二区理论影院 | 新金梅瓶玉蒲团性奴3 | 97国产精品人妻无码免费 | 最新国产成人综合在线观看 | 99精品国产电影 | 免费视频精品38 | 亚洲欧洲精品成人久久曰影片 | 欲香欲色天天天综合和网 | 偷拍精品视频一区二区三区 | 女bbbbxxx孕妇| 日韩精品一卡二卡三卡四卡2021 | 兽交白浆喷水高潮 | 久久99r66热这里有精品 | 亚洲精品乱码久久久久久中文字幕 | 黄A无码片内射无码视频 | 色戒床震视频片段 |