Prism Silverlight モジュール化方法 QuickStarts
Silverlight MVVM の QuickStart を確認したので、次は モジュール化方法の QuckStart を読み下しながらメモする。
http://msdn.microsoft.com/en-us/library/ff921163(v=pandp.40)
上記のページでは、Prism を利用して、以下のトピックが含まれる
- モジュールの生成 : モジュールは、IModule インターフェースを実装したクラス
- モジュールの登録 : モジュールは、以下の方法で登録できる
- コードに直接記述 : アプリケーションの モジュールカタログに 直接記述できる
- XAML : Prism では、XAMLを使ってモジュールカタログをロードできる
- モジュールの依存関係の登録 : モジュールは、依存関係を持つことができ、Prism は依存関係の管理(再帰的な依存や重複を含む)を提供する。
- モジュールの初期化 : Prism では、以下の2種類の方法をサポートする
- 利用可能時 : モジュールは、利用可能になると同時に初期化される。モジュールはアプリケーションの開始時にダウンロードされる
- オンデマンド : モジュールは、アプリケーションがリクエストしたときに初期化される。モジュールは、アプリケーションの要求によりバックグラウンドでダウンロードが開始される
- バックグラウンドでのモジュールダウンロード : モジュールは、バックグラウンドで非同期に関連するXAPファイルがダウンロードされ、XAPファイルへロードされ、初期化される。Prism は XAP が重複してダウンロードされるのを防ぐ。
- 進捗の表示 : アプリケーションは、進捗の変更イベントを受け取ることができる
- ダウンロード完了時のアクション : アプリケーションは、ロード完了のイベントを受け取り、ロードと初期化が完了したときのアクションを設定できる
- 異なった DI コンテナの活用 :
- MEF(Managed Extensibility Framework) によるモジュール化 : .NET Framework 4 から利用できるようになったコンテナ
- Unity による モジュール化 : 以前から利用されてきたコンテナ
シナリオ
6つのモジュール、ModlueA,ModuleB … ModuleF
モジュール | 定義の場所 | 初期化 | ダウンロード | 依存 |
A | コード | 利用可能時 | アプリケーションと同時 | D |
B | XAML | 利用可能時 | バックグラウンド | |
C | コード | オンデマンド | アプリケーションと同時 | |
D | XAML | 利用可能時 | バックグラウンド | |
E | XAML | オンデマンド | バックグラウンド | |
F | XAML | オンデマンド | バックグラウンド | E |
どのモジュールも、コントロール。モジュールコントロールは、初期化されているか、ダウンロード中か等を表示し、オンデマンドモジュールは、クリックにより初期化を要求する。ツールチップを提供し、現在の初期化状況などを表示する。
モジュール化 QuickStart のユーザーインターフェース(Silverlight)
ビルドと実行
- Silverlight only – Open Modularity With Mef QuickStart.bat を実行するとソリューションが起動する
- ModularityWithMef.Silverlight.Web プロジェクトを右クリックし、スタートアッププロジェクトに設定を選択
- F5 で実行
ウォークスルー
1.メインウィンドウに、モジュールのセットが表示されており、それぞれの初期化状況が表示されている、アプリケーションは、モジュールBとモジュールDのダウンロードを開始する。
モジュールB および D は利用可能になったら、初期化され、バックグラウンドでダウンロードされる。
モジュールAも利用可能になったら初期化されるが、モジュールD依存している。
なので、モジュールDのダウンロードが完了するまで、モジュールAは初期化されない。
2.モジュールAにマウスをホバーすると、ツールチップが表示される
3.モジュールCをクリックするとロードされる
4.モジュールFをクリックすると、モジュールEおよびモジュールFがロードされる
モジュールFは、モジュールEに依存しているため、モジュールEが初期化されるまで、初期化されない。
実装の詳細
アプリケーションの開始
アプリケーションは、Bootstrapper をアプリケーションの開始およびメインページの初期化に利用します。
App.xaml.cs
private void Application_Startup(object sender, StartupEventArgs e) { // The boostrapper will create the Shell instance, so we don't need to set the RootVisual QuickStartBootstrapper bootstrapper = new QuickStartBootstrapper(); bootstrapper.Run(); }
Bootstrapper は、Silverlight アプリケーションに、RootVisual をセットするために CreateShell テンプレート メソッドをオーバーライドします。
QuickStartBootstrapper.cs
public class QuickStartBootstrapper : MefBootstrapper { protected override DependencyObject CreateShell() { return this.Container.GetExportedValue(); } :
モジュールの生成
IModule インターフェースを実装した、6つのモジュールが生成される。
MEF利用時(Unityの場合、アトリビュートは不要)
[ModuleExport(typeof(ModuleA), DependsOnModuleNames = new string[] {"ModuleD"})] public class ModuleA : IModule { : }
MEFの場合、ModuleExport アトリビュートは、MEFに IModule の派生クラスを公開する。
モジュールの登録
いくつかのモジュールは、直接アプリケーションから参照され、いくつかは、XAMLから参照され、バックグラウンドでダウンロードされる。
Bootstrapper は、CreateModuleCatarog テンプレートメソッドをXAMLファイルを使ってモジュールを登録するためにオーバーライドする。
protected override IModuleCatalog CreateModuleCatalog() { // When using MEF, the existing Prism ModuleCatalog is still the place to configure modules via configuration files. return Modularity.ModuleCatalog.CreateFromXaml(new Uri("/ModularityWithMef.Silverlight;component/ModulesCatalog.xaml", UriKind.Relative)); }
MEF は、モジュールとダウンロードするXAPを結びつけるメカニズムを提供していない。Prism の ModuleCatalog は MEF コンテナがオンデマンドでバックグラウンドでのダウンロードサポートを利用する。
MEF DeploymentCatalog は、XAPファイルをダウンロードするのに利用される。
MEFを利用する場合、Bootstrapper クラスは、AggregateCatalog がモジュールと型の発見を提供する。ConfigureAggregateCatalog メソッドをオーバーライドする。
protected override void ConfigureAggregateCatalog() { base.ConfigureAggregateCatalog(); // Add this assembly to export ModuleTracker this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(QuickStartBootstrapper).Assembly)); // Module A is referenced in in the project and directly in code. this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(ModuleA.ModuleA).Assembly)); // Module C is referenced in in the project and directly in code. this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(ModuleC.ModuleC).Assembly)); }
モジュールのロード
開始時およびオンデマンドでのモジュールロード、バックグラウンドでのダウンロード、進捗表示、モジュール間の依存関係のデモを含む。
Shell は UIからのモジュールをロードするリクエストに応え、ModuleManager.LoadModule メソッドを呼び出す
Shell.xaml.cs
private void ModuleC_RequestModuleLoad(object sender, EventArgs e) { // The ModuleManager uses the Async Events Pattern. this.ModuleManager.LoadModule(WellKnownModuleNames.ModuleC); }
Shell はダウンロードの進捗を、ModuleManager.ModuleDownloadProgressChange イベント から通知される。
this.ModuleManager.ModuleDownloadProgressChanged += this.ModuleManager_ModuleDownloadProgressChanged;
private void ModuleManager_ModuleDownloadProgressChanged(object sender, ModuleDownloadProgressChangedEventArgs e) { this.moduleTracker.RecordModuleDownloading(e.ModuleInfo.ModuleName, e.BytesReceived, e.TotalBytesToReceive); }
Shell は、モジュールのダウンロードが完了し、初期化されたのを、ModuleManager.LoadModuleComplete イベントから通知される。
this.ModuleManager.LoadModuleCompleted += this.ModuleManager_LoadModuleCompleted;
private void ModuleManager_LoadModuleCompleted(object sender, LoadModuleCompletedEventArgs e) { this.moduleTracker.RecordModuleLoaded(e.ModuleInfo.ModuleName); }
モジュール化でキーとなるクラス
- ModuleCatalog : アプリケーションでのモジュールおよびモジュールグループのメタデータのカタログ
- ModuleManager : モジュールの初期化を制御
- ModuleInitializer : ModuleManager をモジュールの生成時に補助する
- IModlueTypeLoader : モジュールをファイルシステムやリモートサーバーから参照する派生型のためのインターフェース(例 XapModuleTypeLoader)
- Bootstrapper/MefBootstrapper/UnityBootstrapper : モジュール式のPrismアプリケーションの初期化を開始を補助する
受入テスト
テスト用のソリューションが同梱されているが、VS Express エディションでは、読み込めず。。。