MEF中的每一個可進行動態裝配的導出部件都是具有生命周期的,在沒有特別需求的情況下一般都沒有對生命周期進行管理,而實際上 MEF已為每一個部件進行了默認的生命周期管理,MEF的生命周期分為三種:Any、Shared及NonShared,被定義在 System.ComponentModel.Composition.CreationPolicy枚舉對象中。
namespace System.ComponentModel.Composition
{
public enum CreationPolicy
{
Any = 0,
Shared = 1,
NonShared = 2,
}
}
Any表示可共享或不共享,部件的實例用MEF容器根據不同的請求需求自動控制;Shared表示共享部件,既Shared類型的插件部件可以在 多個MEF組合容器中共用;其次是NonShared類型,表示不共享部件實例,每當有新的請求就會創建一個新的對象實例。在MEF中,通過 PartCreationPolicyAttribute特性實現對部件的生命周期配置。
public interface IBookService
{
string GetBookName();
}
[PartCreationPolicy(CreationPolicy.Any)]
[Export(typeof(IBookService))]
public class MEFBookService : IBookService
{
public string GetBookName()
{
return "《MEF程序設計指南》";
}
}
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export(typeof(IBookService))]
public class ASPNETBookService : IBookService
{
public string GetBookName()
{
return "《ASP.NET項目案例》";
}
}
[PartCreationPolicy(CreationPolicy.Shared)]
[Export(typeof(IBookService))]
public class SLBookService : IBookService
{
public string GetBookName()
{
return "《Silverlight高級編程》";
}
}
如上示例代碼分別演示了使用Any、Shared及NonShared類型的生命周期托管類型對不同的對象進行導出部件配置。接下來通過導入部件 並加入生命周期托管篩選,詳細應用如下代碼塊所示:
public partial class MainPage : UserControl
{
[ImportMany(RequiredCreationPolicy = CreationPolicy.Shared)]
public List<IBookService> Service { get; set; }
public MainPage()
{
InitializeComponent();
CompositionInitializer.SatisfyImports(this);
//得到成功裝配的部件總數為2,因為Any類型是可以共存於多個MEF容器的。
int count = Service.Count;
}
}
表面上看去和上一篇指南中介紹的部件的篩選過濾功能非常相似,不同是的過濾篩選是通過自定義篩選策略實現,而這裡是通過MEF生 命周期范圍托管來實現的。在實際的項目開發中需根據不同的應用場景確定具體的技術實現方案。
除了容器部件的生命周期托管,我們也得考慮部件容器自身的生命周期,容器什麼時候釋放資源,時候時候釋放其內部部件的資源占用 等。為了提高系統的整體性能,MEF建議將每一個可導入部件實現IDisposable 接口,用於資源的占用處理,如果部件從MEF容器中移除那 麼所對應占用的資源也會自動的清理。這裡需要注意一點,就是當組合容器被釋放掉後遲延加載的操作就不能再繼續工作了,會拋出 System.ObjectDisposedException異常。
如上圖所示,MEF的容器是具有層次結構的,最高層級容器為程序直接應用級容器,可以通過以下的代碼獲取到。
var catalog = new AssemblyCatalog(typeof(MainPage).Assembly);
var container = new CompositionContainer(catalog);
位於頂級容器之下的子容器,通常來說都是控制著一些可動態裝配的部件對象,如同上一篇指南中介紹到使用過濾器篩選部件的應用案 例,通過過濾表達式從頂級容器中進行篩選,得出了新的MEF容器child,child托管著根據條件過濾篩選出來的所有結果部件對象。詳細代 碼如下:
//獲取當前應用程序目錄
var catalog = new AssemblyCatalog(typeof(MainPage).Assembly);
//將目錄裝載進MEF組合容器
var parent = new CompositionContainer(catalog);
//通過元數據過濾篩選出元數據名稱為"UC"值為"CC"的組合部件
var filteredCat = new FilteredCatalog(catalog,
def => def.Metadata.ContainsKey("UC") &&
def.Metadata["UC"].ToString() == "CC");
var child = new CompositionContainer(filteredCat, parent);
var control = child.GetExportedValue<UserControl>();
文章出處:http://beniao.cnblogs.com/