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)

prism_qs_module01

ビルドと実行

  1. Silverlight only – Open Modularity With Mef QuickStart.bat を実行するとソリューションが起動する
  2. ModularityWithMef.Silverlight.Web プロジェクトを右クリックし、スタートアッププロジェクトに設定を選択
  3. F5 で実行

ウォークスルー

1.メインウィンドウに、モジュールのセットが表示されており、それぞれの初期化状況が表示されている、アプリケーションは、モジュールBとモジュールDのダウンロードを開始する。

prism_qs_module02

モジュールB および D は利用可能になったら、初期化され、バックグラウンドでダウンロードされる。

モジュールAも利用可能になったら初期化されるが、モジュールD依存している。

なので、モジュールDのダウンロードが完了するまで、モジュールAは初期化されない。

2.モジュールAにマウスをホバーすると、ツールチップが表示される

prism_qs_module03

3.モジュールCをクリックするとロードされる

prism_qs_module04

4.モジュールFをクリックすると、モジュールEおよびモジュールFがロードされる

prism_qs_module05

モジュール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 エディションでは、読み込めず。。。

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

前の記事

Prism Basic MVVM QukickStart

次の記事

Prism UI 合成 QuickStart