本篇是接着上篇Windows phone 應用開發[6]-Managed Extensibility Framework應用程序擴展 基礎之上而來. 關於Managed Extensibility FrameWork[MEf]基礎概念這裏再也不贅述.MEF 做爲.NET 4一部分.同時也支持Silverlight4 版本.但因目前官方並無推出Managed Extensibility Framework For Windows phone 版本. 對Codeplexhttp://mef.codeplex.com/上類庫並不支持Windows phone. 這裏介紹另一種方式在Windows phone 中使用MEF.並以一個簡單實例 拋磚引玉.git
在開始介紹以前若是你對MEf For Windows phone 中使用存在問題和相關的技術瓶頸 想了解一番能夠閱讀以下文章:github
MEf For Windows phone By damonpayne:sql http://www.damonpayne.com/post/2010/06/25/MEF-for-Windows-Phone-7.aspxshell |
MSAF分別針對原ComponentModel和Composition.Initialization空間作了Windows phone 類庫的移植. 而如上類庫正是MEF的核心.MSAF框架主要做用是提供了一種標準方法在Windows phone應用程序中添加對使用狀況加以跟蹤並支持第三方數據分析的功能.這個我會下篇中Windows phone採集用戶數據和行爲分析上講解.windows
Well 彷佛MEF支持問題就如此意外的迎刃而解了.以下來作一個簡單實例來驗證.如今提出一個簡單需求咱們宿主程序中要經過MEF方式集成一個管理分類的組件.組件和Windows phone宿主程序關係以下:app
以建立一個Windows phone的類庫形式來實現這個組件 建立類庫並命名-MEFCommon.Data.首先添加MEF 類庫的引用:框架
分別引用了元MSAF源碼中System.ComponentModel和Composition.Initialization兩個DLL.建立一個封裝組件分類操做的接口IAppCatalog 添加引用以下:ide
- using System.ComponentModel;
- using System.ComponentModel.Composition;
- using System.ComponentModel.Composition.Hosting;
- public interface IAppCatalog
- {
- bool AddCatalog(AppCatalog newAppCatalog);
- List<AppCatalog> GetAllAppCatalogList();
- }
同時在該類以IAppCatalog接口做爲契約名向MEF開放.該類一方面提供分類的所有數據同時可以執行添加分類的操做.以下咱們要在一個Windows phone宿主程序中用到分類組件提供分類數據.綁定UI上顯示,定義一個UI上可操做的ViewModel:post
- public class AppCatalog_ViewModel:BasicViewModel
- {
- public AppCatalog_ViewModel()
- {
- CompositionInitializer.SatisfyImports(this);
- }
- public ObservableCollection<AppCatalog> appCatalogCollection = new ObservableCollection<AppCatalog>();
- public ObservableCollection<AppCatalog> AppCatalogCollection
- {
- get { return this.appCatalogCollection; }
- set
- {
- this.appCatalogCollection = value;
- base.NotifyPropertyChangedEventHandler("AppCatalogCollection");
- }
- }
- [Import(typeof(IAppCatalog))]
- public IAppCatalog CurrentCatalogData { get; set; }
- public void LoadAppCatalogData()
- {
- if (this.CurrentCatalogData != null)
- {
- if (this.CurrentCatalogData.GetAllAppCatalogList().Count > 0)
- {
- var catalogList = this.CurrentCatalogData.GetAllAppCatalogList();
- this.appCatalogCollection.Clear();
- catalogList.ForEach(x => { this.appCatalogCollection.Add(x); });
- }
- }
- }
- }
首先在ViewModel定義一個以Import標識IAppcatalog類型屬性用來接收組件中經過MEF須要傳遞的數據.其實這就是宿主程序一個擴展點.一樣這個Windows phone宿主程序須要添加對組件類庫和MEF 引用.如今有了組件的數據 和宿主程序的擴展點接入.Well,要實現組件與宿主程序之間通訊則須要經過MEF創建組合的關聯關係. 而這個組合關係引用須要在應用程序啓動是調用.上篇中咱們採用是一個Console應用程序直接寫在Main方法.做爲Windows phone固然也能夠直接寫在Launching和Activated事件中.固然最好的方式是建立一個實現IApplicationService接口的應用程序服務.能夠得到更好的代碼封裝和關注分離的效果 建立Service以下:ui
- public class MEFAppCatalogService:IApplicationService
- {
- public MEFAppCatalogService()
- {
- CompositionHost.Initialize
- (new AssemblyCatalog(Application.Current.GetType().Assembly),
- new AssemblyCatalog(typeof(MEFCommon.Data.IAppCatalog).Assembly));
- }
- public void StartService(ApplicationServiceContext context) { }
- public void StopService() { }
- }
在構造方法中.調用CompositionHost對象Initialize()方法.相對於上篇咱們直接經過定義CompositionContainer容器的方式.而目前CompositionHost對象提供用於控制 CompositionInitializer 所使用的容器的靜態方法.兩者效果是一致的. Initialize()方法在構造是能夠接受任意數量的目錄. 這和AggregateCatalog對象指定MEF解析範圍是一致的.目錄適用於定義MEF在解析類型是須要檢索的位置範圍.而引用的對象AssemblyCatalog則分別提供對分類組件類庫和宿主應用程序的靜態引用.
接着指定運行的位置.向App.xaml內Application.ApplicationLifetimeObjects集合添加一個MEFAppCatalogService實例.則宿主程序會在任何應用程序代碼運行以前調用服務的Initialize方法來初始化MEF的管理容器.
- <Application.ApplicationLifetimeObjects>
- <!--Required object that handles lifetime events for the application-->
- <shell:PhoneApplicationService
- Launching="Application_Launching" Closing="Application_Closing"
- Activated="Application_Activated" Deactivated="Application_Deactivated"/>
- <mef:MEFAppCatalogService></mef:MEFAppCatalogService>
- </Application.ApplicationLifetimeObjects>
最後就是經過在ViewModel夠着方法中調用CompositionInitializer對象的SatisfyImports()方法實現填充指定組件的導入.[observerCollection集合已經綁定UIlistBox控件:
- //組件導入
- CompositionInitializer.SatisfyImports(this);
如今運行Windows phone應用程序看分類組件提供分類數據能拿到:
ok.成功經過MEF框架宿主程序自動感知的靈活方式添加組件並得到組件提供分類數據.證實MASF提供MEF類庫是可行的.到這了不由有人會問相對上篇難道沒有其餘方式創建宿主和組件之間組合關係?答案是確定的.
只不過若是咱們不以Service形式.咱們創建組件關係.這段創建組合關係代碼放在那? 應該採用什麼方式來組合? 來看看Mainpage綁定ViewModel時:
- //Bind ViewModel
- private AppCatalog_ViewModel appcatalog_ViewModel = null;
- void MainPage_Loaded(object sender, RoutedEventArgs e)
- {
- if (this.appcatalog_ViewModel == null)
- this.appcatalog_ViewModel = new AppCatalog_ViewModel();
- this.appcatalog_ViewModel.LoadAppCatalogData();
- this.DataContext = appcatalog_ViewModel;
- }
- //顯示創建關聯關係
- AggregateCatalog mefCatalog = new AggregateCatalog();
- mefCatalog.Catalogs.Add(new AssemblyCatalog(Application.Current.GetType().Assembly));
- mefCatalog.Catalogs.Add(new AssemblyCatalog(typeof(MEFCommon.Data.IAppCatalog).Assembly));
- CompositionContainer mefContainer = new CompositionContainer(mefCatalog);
- mefContainer.ComposeParts(this);
經過AggregateCAtalog顯示指定MEF解析類型須要檢索的位置範圍。編譯運行發現效果是一致的.
關於這兩種方式.最簡潔使用就是CompositionInitializer對象提供靜態控制.把更多的工做交給MEF自身去作. 另一個好處就是能夠隨時隨地在程序中添加MEF組合關係和檢索位置的範圍.這是顯示定義CompositionContainer 容器方式所沒法直接作到的.
Well關於MEF終於歷經屢次驗證終於可以成功運行在Windows phone應用程序中.本篇只是介紹簡單使用方法.目的是拋磚引玉.體現MEF也可以在Windows phone擴展組件能力和靈活的方式都值得咱們在實際項目加以實踐. 算是提出MEF 在Windows phone中使用一種解決方案.若是任何問題請在評論中提出.以下會給出本篇實例源碼和MASF MEF For windows phone版本的DLL.
本篇實例代碼見附件。
MEF For windows Phone DLL文件見附件。
參考資料:
MEF For Windows phone 7 By DAmon Payne
Microsoft Silverlight Analyics FrameWork Codeplex
可見每次都會Load時從新構造並調用ViewModel構造方法.考慮能夠把組合關係代碼放在這.CompositionInitializer對象提供了對MEF容器的靜態方法控制.固然咱們也能夠像上篇同樣顯示的定義一個CompositionContainer 容器的方式直接管理. 能夠把原ViewModel中代碼替換成:
建立AppCatalogOperator類實現該接口:
- [Export(typeof(IAppCatalog))]
- public class AppCatalogOperator:IAppCatalog
- {
- public List<AppCatalog> OperatorCatalogList = new List<AppCatalog>();
- public bool AddCatalog(AppCatalog newAppCatalog)
- {
- //No Check Reply
- if(newAppCatalog!=null)
- this.OperatorCatalogList.Add(newAppCatalog);
- return true;
- }
- public List<AppCatalog> GetAllAppCatalogList()
- {
- this.OperatorCatalogList.Clear();
- this.OperatorCatalogList.Add(new AppCatalog() { CatalogName = "Music+Video", CatalogNote = "Important for Common User" });
- this.OperatorCatalogList.Add(new AppCatalog() { CatalogName = "Game", CatalogNote = "Different Kind of Game platform" });
- this.OperatorCatalogList.Add(new AppCatalog() { CatalogName = "Book", CatalogNote = "Reader" });
- return this.OperatorCatalogList;
- }
- }
接口中分別定義兩個操做方法.一個用來添加分類方法 另一個獲取全部分類的數據方法:
這篇文章中做者Damonpayne很詳細闡述了MEF 發展的過程以及相對Windows phone 開發不支持的一些相關特性相似:System.Reflection.Emit剔除. 針對MEF操做一樣也不支持IQueryable接口的類Linq操做等.並提出本身的一套在Windows phone 中使用MEF的解決方案.惋惜的是做者直接給一個封裝不完整DLL.並刪除下載頁面.通過實際代碼嘗試Damonpayne給出的一條DeadWay.
而欣慰的老是有人在無心間給你額外的驚喜. 在我看Microsoft Silverlight Analytics Framework[MSAF]源碼時意外的發現.這個開源框架中盡然移植一個Windows phone 版本的MEF: