日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用MEF方便的扩展

發(fā)布時(shí)間:2025/3/15 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用MEF方便的扩展 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.


概述

Managed Extensibility Framework(MEF)是.NET平臺(tái)下的一個(gè)擴(kuò)展性管理框架,它是一系列特性的集合,包括依賴注入(DI)以及Duck Typing等。MEF為開發(fā)人員提供了一個(gè)工具,讓我們可以輕松的對(duì)應(yīng)用程序進(jìn)行擴(kuò)展并且對(duì)已有的代碼產(chǎn)生最小的影響,開發(fā)人員在開發(fā)過程中根據(jù)功能要求定義一些擴(kuò)展點(diǎn),之后擴(kuò)展人員就可以使用這些擴(kuò)展點(diǎn)與應(yīng)用程序交互;同時(shí)MEF讓應(yīng)用程序與擴(kuò)展程序之間不產(chǎn)生直接的依賴,這樣也允許在多個(gè)具有同樣的擴(kuò)展需求之間共享擴(kuò)展程序。

本文將介紹一下Managed Extensibility Framework的一些簡單使用。

簡單依賴注入

大家可以去這里http://code.msdn.microsoft.com/mef下載MEF的CTP版本,在下載包里有一些簡單的文檔和示例。下面先來看一個(gè)簡單的示例,這里輸出一個(gè)字符串:

Code 1 ? static voidMain(string[] args)
{
Console.WriteLine("This is a simple string.");
}

現(xiàn)在考慮到該字符串將來可能發(fā)生變化,不知道該字符串將從何處取得,也就是說這里有可能是一個(gè)變化點(diǎn),也是一個(gè)擴(kuò)展點(diǎn),那我們現(xiàn)在使用MEF對(duì)其進(jìn)行重新設(shè)計(jì),我們將會(huì)把這個(gè)過程分成兩個(gè)部分,一部分用于提供字符串,而另一部分則用來使用字符串,定義一個(gè)字符串提供程序,大家注意到這里為OutputTitle屬性添加了一個(gè)Export特性,這標(biāo)識(shí)著此處為一個(gè)輸出,它使的MEF能夠?qū)ζ溥M(jìn)行識(shí)別,如下代碼所示:

Code 2 ? public class WeekStringProvider
{
[Export("Caption")]
public String OutputTitle
{
get { return "星期六"; }
}
} ?

這里只是定義了一個(gè)簡單的屬性,其實(shí)在同一個(gè)類型可以定義多個(gè)輸出,Export同時(shí)指定了一個(gè)字符串的契約名稱,這意味著任何匹配契約名稱的程序都可以使用該擴(kuò)展。除此之外,我們還可以指定一個(gè)類型來代替字符串的契約名稱,后面會(huì)說到。我們?cè)俣x一個(gè)輸入,即用來消費(fèi)該字符串,同樣是一個(gè)簡單的屬性,不過這次添加的是Import特性:

Code 3 ? public class Client
{
[Import("Caption")]
public String OutputTitle
{ get; set; }
}
?

現(xiàn)在有了輸出和輸入,就可以在主程序中進(jìn)行調(diào)用了,需要?jiǎng)?chuàng)建一個(gè)CompositionContainer容器,并添加所有的組件到該容器中,再調(diào)用它的Bind()方法,一旦調(diào)用該方法后,就可以使用所有的組件了,如下代碼所示:

Code 4 static void Main(string[] args)
{
Client client =new Client();
CompositionContainer container =new CompositionContainer();
container.AddComponent<Client>(client);
container.AddComponent<WeekStringProvider>(new WeekStringProvider());
container.Bind();
Console.WriteLine(client.OutputTitle);
}


?

輸出結(jié)果如下圖所示:

現(xiàn)在我們?cè)俣x另外一個(gè)擴(kuò)展程序,讓它返回一個(gè)日期字符串,如下代碼所示:

Code 5 ? public class DateStringProvider
{
[Export("Caption")]
public String OutputTitle
{
get { return DateTime.Now.ToLongDateString(); }
}
}

?

修改一下組件注冊(cè)程序,如下代碼所示:

Code 6 ? static void Main(string[] args)
{
Client client =new Client();
CompositionContainer container =new CompositionContainer();
container.AddComponent<Client>(client);
container.AddComponent<DateStringProvider>(new DateStringProvider());
container.Bind();
Console.WriteLine(client.OutputTitle);
}

?

輸出結(jié)果如下圖所示:

?

上面的示例中我們是使用了命名契約,除此之外,還可以使用類型契約,如定義一個(gè)字符串提供者程序的接口:

Code 7 ?public interface IStringProvider? {?String?OutputTitle {?get;?set; } }

現(xiàn)在輸出和輸入對(duì)應(yīng)的修改為如下代碼:

Code 8 public class DateStringProvider : IStringProvider
{
[Export(typeof(IStringProvider))]
public String OutputTitle
{
get { return DateTime.Now.ToLongDateString(); }
}
} Code 9 ? public class Client
{
[Import(typeof(IStringProvider))]
public String OutputTitle
{ get; set; }
}

?

運(yùn)行后可以看到它與前面的示例效果是一樣的。

Duck Typing支持

了解DI的朋友可能都有這樣的疑問,其實(shí)上面的代碼就是一個(gè)依賴注入,微軟模式與實(shí)踐團(tuán)隊(duì)已經(jīng)開發(fā)出了Unity,為什么還需要一個(gè)MEF呢?其實(shí)MEF的定位并不是DI,在前面我已經(jīng)說過,它主要是用于應(yīng)用程序擴(kuò)展管理,下面我們?cè)倏匆粋€(gè)示例,它在這方面具有什么樣的優(yōu)勢(shì),看下面這段代碼:

Code 10 [ContractType("TerryLeeCalculatro")]
public interface ICalculator
{
int Execute(int x,int y);
}

public class Client
{
[Import(typeof(ICalculator))]
public ICalculator Calculator { get; set; }
}

?

?

這里我們定義了一個(gè)輸入,它里面具有一個(gè)ICalculator的屬性,也就是說它需要的輸入是一個(gè)類型是ICalculator的實(shí)例。現(xiàn)在我們定義輸出,如下代碼所示:

Code 11 [Export(typeof(ICalculator))]
public class SubCalculator : ICalculator
{
public int Execute(int x, int y)
{
return x - y;
}
}


?

在主函數(shù)中進(jìn)行調(diào)用:

Code 12 static void Main(string[] args)
{
Client client =new Client();
CompositionContainer container =new CompositionContainer();
container.AddComponent<Client>(client);
container.AddComponent<SubCalculator>(new SubCalculator());
container.Bind();
Console.WriteLine(client.Calculator.Execute(1,2));
}


?

輸出結(jié)果如下圖所示:

?

現(xiàn)在我們需要對(duì)該程序擴(kuò)展,讓其計(jì)算結(jié)果為兩個(gè)數(shù)相加,如果使用DI,我們可能會(huì)想到,再編寫一個(gè)支持加法計(jì)算的類,讓其實(shí)現(xiàn)ICalculator接口,然而這里我們重新定義了一個(gè)新的接口IMyCalculator:

Code 13

?

[ContractType("TerryLeeCalculatro")]
public interface IMyCalculator
{
int Execute(int x, int y);
}

[Export(typeof(IMyCalculator))]
public class AddCalculator :IMyCalculator
{
public int Execute(int x, int y)
{
return x + y;
}
}

這里重新定義了一個(gè)新接口IMyCalculator,我們?yōu)樗O(shè)置的契約類型和前面定義的接口ICalculator一致。而AddCalculator實(shí)現(xiàn)這個(gè)接口,同樣用Export標(biāo)識(shí)它為一個(gè)輸出。最后調(diào)用程序如下:

Code 14 ? static void Main(string[] args)
{
Client client =new Client();
CompositionContainer container =new CompositionContainer();
container.AddComponent<Client>(client);
container.AddComponent<AddCalculator>(new AddCalculator());
container.Bind();
Console.WriteLine(client.Calculator.Execute(1,2));
} ?

輸出結(jié)果如下圖所示:

?

大家可能已經(jīng)意識(shí)到了,上面示例中的輸入需要ICalculator類型,而我們擴(kuò)展的輸出卻是IMyCalculator類型,它僅僅是與ICalculator標(biāo)識(shí)為相同的契約類型,這種方式帶來了極大的靈活性,也就是說我們?cè)趯?duì)原有應(yīng)用程序進(jìn)行擴(kuò)展時(shí),并不需要與原有應(yīng)用程序產(chǎn)生任何依賴,可以獨(dú)立的進(jìn)行擴(kuò)展。

Plug-In支持

在前面的例子中,始終有一個(gè)問題沒有解決,就是當(dāng)每次編寫一個(gè)擴(kuò)展程序后,都需要修改代碼向CompositionContainer中注冊(cè)組件,這樣其實(shí)并沒有實(shí)現(xiàn)真正的擴(kuò)展,我們希望的擴(kuò)展是Plug-In機(jī)制。在MEF對(duì)于Plug-In提供了很好的支持,它提供了DirectoryWatchingComponentCatalog類來對(duì)指定的目錄進(jìn)行監(jiān)視,就是說我們定義好了輸入之后,只要把相關(guān)的輸出組件放在指定目錄中,MEF會(huì)通過反射來進(jìn)行自動(dòng)查找,如我們定義這樣的一個(gè)輸入:

Code 15 public class User
{
[Import("Role")]
public String Role { get; set; }
}

?

現(xiàn)在定義輸出,我們把它放在一個(gè)單獨(dú)的類庫項(xiàng)目中:

Code 16 ? public classDatabaseProvider { [Export("Role")] public String AvailableRole { get { return"Developer"; } } }

?

在主調(diào)用程序的目錄下,我們創(chuàng)建一個(gè)Extensions的目錄,然后把相關(guān)的擴(kuò)展組件都放在該目錄下,并在主調(diào)用程序中,為DirectoryWatchingComponentCatalog實(shí)例加入Extensions目錄,這樣就避免了與具體的擴(kuò)展應(yīng)用程序產(chǎn)生依賴,如下代碼所示:

Code 17 static void Main(string[] args)
{
User user =new User();
DirectoryWatchingComponentCatalog catalog =new DirectoryWatchingComponentCatalog();
catalog.AddDirectory(@"Extensions");
CompositionContainer container = new CompositionContainer(catalog.Resolver);
container.AddComponent<User>(user);
container.Bind();
Console.WriteLine(user.Role);
Console.ReadLine();
}
?

?

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

??

對(duì)于MEF來說,Duck Typing支持以及Plug-In支持才是它的優(yōu)勢(shì)所在,它不是一個(gè)簡單的DI容器,而是一個(gè)真正的管理擴(kuò)展框架。當(dāng)然了現(xiàn)在MEF還處于CTP階段,很多功能還不是很完善。在8月初,微軟還特意請(qǐng)到了Castle之父Hammett加入該項(xiàng)目組,擔(dān)任Program Manager,MEF的未來值得期待,更值得期待的是MEF將會(huì)為Silverlight應(yīng)用程序開發(fā)一個(gè)MEF子集,讓我們對(duì)于Silverlight程序也能夠方便的進(jìn)行擴(kuò)展。

Managed Extensibility Framework的官方主頁是:http://code.msdn.microsoft.com/mef

總結(jié)

本文簡單介紹了Managed Extensibility Framework的一些使用,希望對(duì)大家有所幫助。

轉(zhuǎn)載于:https://www.cnblogs.com/tuyile006/archive/2011/06/02/2070092.html

總結(jié)

以上是生活随笔為你收集整理的使用MEF方便的扩展的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。