Prism開発者ガイド-パート4、モジュラーアプリケーションの開発

目次

  1. はじめに
  2. Prismアプリケーションの初期化
  3. コンポーネント間の依存関係の管理
  4. モジュラーアプリケーション開発
  5. MVVMパターンの実装
  6. 高度なMVVMシナリオ
  7. ユーザーインターフェイスの作成

    1. ユーザーインターフェイスのガイドライン
  8. ナビゲーション
    1. ビューベースのナビゲーション
  9. 疎結合コンポーネント間の相互作用


モジュラーアプリケーションは、単一のユニットに統合できる多くの機能ブロック(モジュール)に分割できるアプリケーションです。 クライアントモジュールは、アプリケーションの機能全体の一部をカプセル化し、通常、相互接続された機能部分の集合です。 これには、ユーザーインターフェイスやビジネスロジックなどのアプリケーション機能などの関連コンポーネントのセット、またはロギング用のアプリケーションレベルサービス、ユーザー認証および承認などのアプリケーションインフラストラクチャの一部が含まれる場合があります。 モジュールは互いに独立していますが、疎結合の方法で相互に対話できます。 モジュラーアプリケーションは、アプリケーションの開発、テスト、展開、および拡張を促進できます。



たとえば、パーソナルバンキングアプリケーションを考えてみましょう。 ユーザーは、アカウント間での送金、請求書の支払い、単一のユーザーインターフェイス(UI)を使用した個人データの更新など、多くの機能にアクセスできます。 ただし、これらの各機能は個別のモジュールにカプセル化されています。 これらのモジュールは相互に通信し、データベースサーバーやWebサービスなどのバックエンドシステムとも通信します。 アプリケーションサービスは、さまざまなモジュールのそれぞれにさまざまなコンポーネントを統合し、ユーザーとの対話を処理します。 ユーザーには、唯一の完全なアプリケーションのように見える統合ビューが表示されます。



次の図は、モジュラーアプリケーションの設計を示しています。



モジュラーアプリケーション



モジュラーアプリケーションを構築する利点



おそらく、アセンブリ、インターフェイス、クラス、および優れたオブジェクト指向開発原則を使用して、適切に設計されたアプリケーションをすでに作成しているでしょう。 この場合、深刻な対策を講じないと、アプリケーションの設計は「モノリシック」のままになります(すべての機能がアプリケーション内で強力に接続された方法で実装されます)。



一方、アプリケーションを構築するためのモジュラーアプローチは、大規模な機能領域を分離し、それらを独立して開発またはテストするのに役立ちます。 これにより、開発とテストが簡単になり、アプリケーションが将来より柔軟で簡単に拡張できるようになります。 モジュール方式の利点は、アプリケーションを管理しやすい部分に分割することにより、アプリケーションアーキテクチャをより柔軟で保守しやすくすることができることです。 各部分は特定の機能をカプセル化し、明確ではあるが疎結合のチャネルを介して統合します。



モジュラーアプリケーション開発のためのPrismサポート



Prismは、実行時にモジュール式アプリケーションを開発し、モジュールを管理するのに役立ちます。 Prism機能を使用すると、モジュラーアプリケーションを構築するために独自のプラットフォームを実装およびテストする必要がないため、時間を節約できます。 Prismは、モジュラーアプリケーションを開発するために次の機能をサポートしています。



基本的な概念



このセクションでは、 IModule



、モジュールのロードプロセス、モジュールカタログ、モジュール間の通信の維持、および依存性注入コンテナーなど、Prismのモジュール方式に関連する基本概念を説明します。



IModule :モジュラーアプリケーションのビルディングブロック



モジュールは、1つの場所に集められた機能コンポーネントとリソースの論理セットです。 モジュールは、個別に開発、テスト、デプロイ、およびアプリケーションに統合できます。 パッケージには、1つ以上のアセンブリを含めることができます。これらのアセンブリは、個別に配置することも、単一のXAPファイルにアセンブルすることもできます。 各モジュールには、モジュール機能を初期化してアプリケーションに統合する中心的なクラスがあります。 このクラスは、 IModule



実装しIModule



。 パッケージをモジュールとして識別するには、 IModule



を実装するクラスがあれば十分です。 IModule



は、 Initialize



メソッドが1つあります。このメソッド内で、モジュール機能を初期化してアプリケーションに統合するために必要なロジックを実装できます。 モジュールの目的に応じて、ユーザーインターフェイスの領域に表現を登録したり、アプリケーションで追加のサービスを利用可能にしたり、機能を拡張したりできます。 次のコードは、モジュールの最小実装を示しています。



 public class MyModule : IModule { public void Initialize() { //    . } }
      
      





ご注意

IModule



によって提供される初期化メカニズムを使用する代わりに、 Stock Trader RIは、ビュー、サービス、およびタイプを登録するための宣言型の属性ベースのアプローチを使用します。


モジュールの寿命



Prismのモジュールロードプロセスには次のものが含まれます。

  1. モジュールの登録/発見。 特定のアプリケーションの実行時にロードされるモジュールは、モジュールディレクトリで定義されます。 ディレクトリには、ロードされたモジュール、その場所、およびロードされる順序に関する情報が含まれています。
  2. モジュールをロードしています。 モジュールを含むアセンブリがメモリにロードされます。 このフェーズでは、ネットワークから、または別のリモートロケーションまたはローカルディレクトリからモジュールをダウンロードする必要があります。
  3. モジュールの初期化。 モジュールクラスを作成し、 IModule



    介してInitialize



    メソッドをIModule





次の図は、モジュールのロードプロセスを示しています。



モジュールの読み込みプロセス



モジュールカタログ



ModuleCatalog



は、アプリケーションが使用できるモジュールに関する情報が含まれています。 ディレクトリは、本質的にModuleInfo



クラスのコレクションです。 各モジュールは、モジュールの名前、タイプ、および場所を格納するModuleInfo



クラスによって記述されます。 ModuleCatalog



ModuleCatalog



インスタンスをModuleCatalog



するためのいくつかの典型的なアプローチがあります。



使用する登録および検出メカニズムの選択は、アプリケーションに必要なものによって異なります。 構成ファイルまたはXAMLファイルを使用すると、アプリケーションはモジュール参照を保存できません。 ローカルディレクトリを使用すると、アプリケーションでモジュールを検出できますが、ファイルで定義する必要はありません。



モジュールのロード時間の管理



Prismアプリケーションは、可能な限り早くモジュールを初期化することができます。これは、利用可能な場合、またはアプリケーションが必要とする場合、オンデマンドとして知られています。 Silverlightアプリケーションの場合、モジュールはアプリケーションと共にロードすることも、アプリケーションの起動後にバックグラウンドでロードすることもできます。 次のモジュールのロード手順を考慮してください。



アプリケーションの分割方法、一般的なユースケース、アプリケーションの起動速度、ダウンロードの数とサイズを考慮して、モジュールのロードと初期化を構成する方法を決定します。



モジュールとアプリケーションの統合



Prismは、アプリケーションのロードに必要なUnityBootstrapper



およびMefBootstrapper



クラスを提供します。 これらのクラスを使用して、モジュールの検出とロードに必要なモジュールマネージャーを作成および構成できます。 モジュールカタログの構成方法をオーバーライドして、XAMLファイル、構成ファイルで定義されたモジュールを登録したり、ディレクトリの場所を指定したりできます。



モジュールのInitialize



メソッドを使用して、モジュールをアプリケーションの他の部分と統合します。 これを行う方法は、アプリケーションの構造とモジュールの内容によって異なります。 以下は、モジュールをアプリケーションに統合するために必要な一般的な手順です。



モジュール間の通信



モジュールが疎結合されるべきであることを考慮しても、それらは互いにデータとメッセージを交換する傾向があります。 疎結合システムにはいくつかの通信パターンがあり、それぞれに長所と短所があります。 原則として、これらのパターンの組み合わせが最終的に使用されます。 これらのパターンの一部を次に示します。



依存性注入とモジュラーアプリケーション



Unity Application Block(Unity)やManaged Extensibility Framework(MEF)などのコンテナーを使用すると、制御の反転(IoC)および依存関係の注入を簡単に使用できます。これらは、疎結合の方法でコンポーネントを接続するのに役立つ強力な開発パターンです。 これにより、コンポーネントは、これらのリンクをハードコーディングする必要なく、依存する他のコンポーネントへのリンクを取得できるため、コードの再利用と柔軟性の向上が得られます。 依存性注入は、疎結合のモジュラーアプリケーションを作成するときに非常に役立ちます。 Prismは、アプリケーションコンポーネントを構成するために使用されるDIコンテナから独立するように設計されました。 コンテナの選択はあなたのビジネスであり、それは基本的な運用特性と好みに大きく依存します。 Microsoftが検討する主な依存関係注入プラットフォームは、UnityとMEFの2つです。



パターンとプラクティスUnity Application Blockは、フル機能の依存性注入コンテナーを導入します。 プロパティベースのインジェクション、コンストラクターベースのインジェクション、およびポリシーインジェクションをサポートしているため、コンポーネント間で動作とポリシーを透過的に導入できます。 また、依存性注入コンテナに典型的な他の多くの機能もサポートしています。



MEF(現在は.NET Framework 4およびSilverlight 4の一部)を使用すると、依存性注入ベースの構成をサポートすることで拡張可能なアプリケーションを作成でき、モジュール式アプリケーション開発をサポートする他の機能も提供します。 これにより、アプリケーションは実行時にコンポーネントを検出し、それらをアプリケーションに統合できます。 MEFは、拡張と構成の大きな機会を提供します。 これらには、アセンブリと型の検出、依存関係の解決、依存関係の挿入、およびアセンブリとXAPファイルを読み込むためのいくつかの機能が含まれます。 Prismは、次のようなMEF関数の使用をサポートしています。



重要な決定



最初に決定する必要があるのは、モジュラーアプリケーションを開発するかどうかです。 前のセクションで説明したように、モジュール式アプリケーションを構築することには多くの利点がありますが、これらの利点を得るために追加の時間と労力が必要です。 それでもモジュール式アプリケーションを開発することに決めた場合は、さらに考慮すべきことがいくつかあります。



次のセクションでは、これらのソリューションについて詳しく説明します。



アプリケーションのモジュールへの分離



モジュール方式でアプリケーションを開発する場合、個別に開発、テスト、および展開できる個別のクライアントモジュールに構造化します。 各モジュールは、アプリケーションの全機能の一部をカプセル化します。 最初に行う必要のある設計上の決定の1つは、アプリケーションの機能を個別のモジュールに分離する方法を決定することです。



モジュールは、一連の関連する機能をカプセル化し、一連の異なる責任を負う必要があります。 モジュールは、アプリケーションの垂直セクションまたはサービスの水平レイヤーを表すことができます。 大規模なアプリケーションには、両方のタイプのモジュールがあります。



  ,



  ,



大規模なアプリケーションでは、モジュールを垂直スライスと水平レイヤーの両方に編成できます。 たとえば、モジュールには次のものが含まれます。



モジュールには、他のモジュールに対する最小限の依存関係セットが必要です。 モジュールが別のモジュールに依存している場合、特定のタイプではなく、共有ライブラリで定義されたインターフェイスを介して、またはEventAggregator



を使用してイベントを介して他のモジュールと通信することにより、モジュールに疎接続する必要があります。



モジュール方式の原則の目的は、機能や技術が追加および削除された場合でも、柔軟で保守しやすく、安定するようにアプリケーションを分割することです。 これを実現する最良の方法は、モジュールが可能な限り独立し、明確に定義されたインターフェースを持ち、可能な限り分離されるようにアプリケーションを開発することです。



プロジェクトとモジュールの比率を決定する


モジュールを作成してパッケージ化する方法はいくつかあります。 推奨される最も一般的な方法は、モジュールごとに1つのアセンブリを作成することです。 これにより、モジュールを論理的に分離し、適切なカプセル化を促進できます。 また、アセンブリをモジュールとして、またはその逆について話すこともできます。 ただし、単一のアセンブリに複数のモジュールが含まれることを妨げるものはありません。場合によっては、ソリューション内のプロジェクトの数を最小限に抑えることが望ましい場合があります。 大規模なアプリケーションには、10〜50個のモジュールがあります。 各モジュールを独自のプロジェクトに転送すると、ソリューションが複雑になり、Visual Studioのパフォーマンスが低下する可能性があります。 プロジェクトまたはアセンブリごとに1つのモジュールに固執したい場合、モジュールまたはモジュールのセットを独自のソリューションに分割することが理にかなっている場合があります。



XAPおよびモジュールファクタリング


Silverlightアプリケーションの場合、モジュールは通常、個別のXAPファイルにパッケージ化されますが、場合によっては、XAPに複数のモジュールがある場合があります。 アプリケーションの実行と新しいオプションの有効化に必要なダウンロードリクエストの数とサイズを最小限に抑えるために必要なXAPファイルの数を検討します。 各モジュールを独自のプロジェクト/アセンブリに分離する場合は、各アセンブリに独自のXAPを展開用に挿入するか、複数のアセンブリを単一のXAPに含めるかを決定する必要があります。



単一のXAPファイルに複数のモジュールを含めるか分割するかの選択に影響するいくつかの要因:



各XAPで同じアセンブリを複数回ロードしないようにするには、次の2つのアプローチを使用できます。



依存性注入を使用して疎結合を実現する



モジュールは、ホストアプリケーションまたは他のモジュールによって提供されるコンポーネントとサービスに依存する場合があります。Prismは、モジュール間の依存関係を登録して、正しい順序でロードおよび初期化する機能をサポートしています。Prismは、ロード後のモジュールの初期化もサポートしています。初期化中に、モジュールは、必要な追加のコンポーネントおよびサービスへのリンクを受信したり、他のモジュールで使用できるようにするために含まれるコンポーネントおよびサービスを登録したりできます。



モジュールは、特定のタイプを直接作成する代わりに、独立したメカニズムを使用して外部インターフェイスのインスタンスを取得する必要があります。彼は、依存性注入コンテナまたはファクトリサービスを通じてこれを行うことができます。 UnityやMEFなどの依存性注入コンテナーを使用すると、型は依存性注入によってインターフェイスインスタンスを自動的に取得できます。 PrismはUnityとMEFの両方と統合して、モジュールが依存性注入メカニズムを簡単に使用できるようにします。

次の図は、コンポーネントおよびサービスへのリンクを取得または登録するために必要なモジュールをロードする一般的なプロセスを示しています。



  .



この例では、アセンブリOrdersModule



はクラスを定義しますOrdersRepository



(順序機能を実装する他のビューおよびクラスとともに)。アセンブリCustomerModule



、サービスによって提供されるインターフェイスに基づくクラスCustomersViewModel



に依存するクラス定義OrdersRepository



します。アプリケーションとダウンロードプロセスの起動には、次の手順が含まれます。

  1. ブートストラップはモジュールの初期化プロセスを開始し、モジュールローダーはをロードして初期化しますOrdersModule



  2. 初期化フェーズOrdersModule



    OrdersRepository



    は、コンテナに登録します。
  3. モジュールローダーがロードされますCustomersModule



    モジュールの読み込み順序は、メタデータに基づいて決定できます。
  4. CustomersModule



    CustomerViewModel



    , . CustomerViewModel



    OrdersRepository



    ( ) . , , OrdersModule



    . CustomerViewModel



    OrderRepository



    .


ご注意

, , OrderRespository



( IOrderRepository



), , , , . , CustomersModule



OrdersModule



.


両方のモジュールは、依存性注入コンテナに暗黙的に依存していることに注意してください。この依存関係は、ブートローダーでのモジュール作成中に導入されます。



基本シナリオ



このセクションでは、アプリケーションでモジュールを操作するときに発生する一般的なシナリオについて説明します。これらのシナリオには、モジュール定義、モジュールの登録と検出、モジュールのロード、モジュールの初期化、モジュールの依存関係の決定、オンデマンドでのモジュールのロード、バックグラウンドでのリモートモジュールのロード、ロードプロセスのステータスの決定が含まれます。コード、XAML、アプリケーション構成ファイル、またはローカルディレクトリをスキャンすることで、モジュールを登録できます。



モジュール定義



モジュールは、個別に開発、テスト、デプロイ、およびアプリケーションに統合できる機能とリソースの論理セットです。各モジュールには、モジュールの初期化とその機能のアプリケーションへの統合を担当する中央クラスがあります。このクラスは、次にIModule



示すようにインターフェイス実装します



 public class MyModule : IModule { public void Initialize() { //  . } }
      
      





ご注意

モジュール名は、アプリケーション全体で一意でなければなりません。


メソッドの実装方法Initialize



は、アプリケーションの要件によって異なります。モジュールクラスタイプ、初期化モード、およびモジュールの依存関係は、モジュールカタログで指定されます。ディレクトリ内の各モジュールに対して、ローダーはモジュールクラスのインスタンスを作成し、methodを呼び出しますInitialize



モジュールは、モジュールカタログで定義された順序で処理されます。実行時の初期化順序は、モジュールがロードされ、使用可能になり、依存関係が満たされるタイミングに依存します。



アプリケーションが使用するモジュールカタログのタイプに応じて、モジュールクラス内の宣言属性またはモジュールカタログファイル内で、モジュールの依存関係を設定できます。以下のセクションでは、より詳細な情報を提供します。



登録とモジュールの検出



アプリケーションがロードできるモジュールは、モジュールディレクトリで定義されます。 Prism Module Loaderは、モジュールカタログを使用して、ダウンロード可能なモジュール、ロードするタイミング、およびロードする順序を決定します。



モジュールカタログは、インターフェイスを実装するクラスですIModuleCatalog



。モジュールカタログクラスは、アプリケーションの初期化中にローダークラスによって作成されます。 Prismは、必要なモジュールカタログを選択できるモジュールカタログのさまざまな実装を提供します。また、メソッドを呼び出すAddModule



か、クラスを継承して、ModuleCatalog



特殊な動作のモジュールカタログを作成することにより、別のデータソースからモジュールカタログを作成することもできます。

ご注意

通常、Prismのモジュールは、依存関係注入コンテナーとCommon Service Locatorを使用して、モジュールの初期化に必要な型インスタンスを取得します。モジュールの登録、検出、ロード、および初期化の完全なプロセスはまったく同じですが、使用されるコンテナーによって詳細は異なる場合があります。アプローチ間のコンテナ固有の違いについては、このトピック全体で説明します。


コードでのモジュールの登録


最も基本的なモジュールカタログは、クラスによって提供されModuleCatalog



ます。このディレクトリを使用して、モジュールのクラスタイプを指定することにより、コードでモジュールを登録できます。初期化モードとモジュール名を設定することもできます。モジュールをクラスModuleCatalog



直接登録するにAddModule



Bootstrapper



、アプリケーションのクラスのメソッド呼び出します。



 protected override void ConfigureModuleCatalog() { Type moduleCType = typeof(ModuleC); ModuleCatalog.AddModule( new ModuleInfo() { ModuleName = moduleCType.Name, ModuleType = moduleCType.AssemblyQualifiedName, }); }
      
      





前の例では、シェルはモジュールを直接参照するため、メソッド呼び出しで使用できるモジュールクラスのタイプを決定しますAddModule



そのため、この例ではtypeof(Module)



、ディレクトリにモジュールを追加するために使用しています。

ご注意

アプリケーションにモジュールのタイプへの直接参照がある場合、上記のようにこのタイプを追加できます。それ以外の場合は、完全修飾タイプ名とアセンブリの場所を提供する必要があります。


コード内の決意モジュールカタログの他の例を見るために参照StockTraderRIBootstrapper.cs



ストックトレーダーRI

ご注意

Bootstrapper



CreateModuleCatalog



, ModuleCatalog



. , ModuleCatalog



, .


XAML


XAMLファイルでモジュールディレクトリを宣言的に定義できます。 XAMLファイルは、作成するモジュールカタログクラスと追加するモジュールを決定します。通常、.xaml



ファイルはリソースとしてシェルプロジェクトに追加されます。モジュールディレクトリは、メソッドを呼び出すことでブートローダーに作成されますCreateFromXaml



。技術的な観点から見るとModuleCatalog



、XAMLファイルはインスタンス化されるオブジェクトの階層を単に定義するだけなので、このアプローチはコードの定義似ています。



次のコード例は、モジュールディレクトリを定義するXAMLファイルを示しています。



 <Modularity:ModuleCatalog xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:Modularity="clr-namespace:Microsoft.Practices.Prism.Modularity;assembly=Microsoft.Practices.Prism"> <Modularity:ModuleInfoGroup Ref="ModuleB.xap" InitializationMode="WhenAvailable"> <Modularity:ModuleInfo ModuleName="ModuleB" ModuleType="ModuleB.ModuleB, ModuleB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> </Modularity:ModuleInfoGroup> <Modularity:ModuleInfoGroup InitializationMode="OnDemand"> <Modularity:ModuleInfo Ref="ModuleE.xap" ModuleName="ModuleE" ModuleType="ModuleE.ModuleE, ModuleE, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <Modularity:ModuleInfo Ref="ModuleF.xap" ModuleName="ModuleF" ModuleType="ModuleF.ModuleF, ModuleF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" > <Modularity:ModuleInfo.DependsOn> <sys:String>ModuleE</sys:String> </Modularity:ModuleInfo.DependsOn> </Modularity:ModuleInfo> </Modularity:ModuleInfoGroup> <!--      --> <Modularity:ModuleInfo Ref="ModuleD.xap" ModuleName="ModuleD" ModuleType="ModuleD.ModuleD, ModuleD, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> </Modularity:ModuleCatalog>
      
      





ご注意

ModuleInfoGroups



同じ.xapファイルまたはアセンブリ内にあるモジュール、同じ方法で初期化されるモジュール、または同じグループ内のモジュールのみに依存関係を持つモジュールをグループ化する便利な方法を提供します。モジュール間の依存関係はモジュール内で定義できModuleInfoGroup



ますが、異なるモジュールのモジュール間の依存関係を指定することはできませんModuleInfoGroups



モジュールをモジュールグループに入れることはオプションです。グループに設定されたプロパティは、グループ内のすべてのモジュールに適用されます。モジュールはグループに属さずに登録することもできます。



クラスでBootstrapper



は、ModuleCatalog



以下に示すように、XAMLファイルがのソースであることを示す必要があります。



 protected override IModuleCatalog CreateModuleCatalog() { return ModuleCatalog.CreateFromXaml( new Uri("/MyProject.Silverlight;component/ModulesCatalog.xaml", UriKind.Relative)); }
      
      





構成ファイルを使用したモジュールの登録


WPFでは、ファイルでモジュール情報を指定できますApp.config



このアプローチの利点は、このファイルがアプリケーションにコンパイルされないことです。これにより、アプリケーションを再コンパイルせずに、実行時にモジュールを簡単に追加または削除できます。



次のコードは、モジュールディレクトリを定義する構成ファイルを示しています。モジュールを自動的にロードする場合は、をインストールしstartupLoaded="true"



ます。



  <modules> <module assemblyFile="ModularityWithUnity.Desktop.ModuleE.dll" moduleType="ModularityWithUnity.Desktop.ModuleE, ModularityWithUnity.Desktop.ModuleE, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="ModuleE" startupLoaded="false" /> <module assemblyFile="ModularityWithUnity.Desktop.ModuleF.dll" moduleType="ModularityWithUnity.Desktop.ModuleF, ModularityWithUnity.Desktop.ModuleF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" moduleName="ModuleF" startupLoaded="false"> <dependencies> <dependency moduleName="ModuleE"/> </dependencies> </module> </modules>
      
      





ご注意

アセンブリがグローバルアセンブリキャッシュまたはアプリケーションと同じフォルダーにある場合でも、属性が必要ですassemblyFile



この属性は、使用するmoduleType



正しい属性にマップするIModuleTypeLoader



ために使用されます。


Bootstrapper



アプリケーションクラスでは、構成ファイルのソースを指定する必要がありますModuleCatalog



これを行うにConfigurationModuleCatalog



は、次のコードに示すようにクラス使用します。



 protected override IModuleCatalog CreateModuleCatalog() { return new ConfigurationModuleCatalog(); }
      
      





ご注意

モジュールをConfigurationModuleCatalog



コードに追加できますこれを使用して、たとえば、アプリケーションの機能に絶対に必要なモジュールがモジュールディレクトリに追加されるようにすることができます。


ご注意

Silverlightは構成ファイルをサポートしていません。Silverlightでの構成にこのアプローチを使用する場合はModuleCatalog



、サーバー上のWebサービスからモジュールの構成を読み取る独自のを作成することをお勧めします。


ローカルディレクトリでのモジュールの検索


このクラスをDirectoryModuleCatalog



使用すると、ローカルディレクトリをWPFのモジュールディレクトリとして設定できます。このモジュールディレクトリは、指定されたフォルダーをスキャンし、アプリケーションにモジュールを提供するアセンブリを探します。このアプローチを使用するには、モジュールクラスの宣言属性を使用して、モジュール名とそれらが持つ依存関係を決定する必要があります。次のコード例は、ローカルディレクトリでアセンブリを検出したときにデータを取り込むモジュールディレクトリを示しています。



 protected override IModuleCatalog CreateModuleCatalog() { return new DirectoryModuleCatalog() {ModulePath = @".\Modules"}; }
      
      





ご注意

Silverlightのセキュリティモデルでは、ファイルシステムからアセンブリを読み込むことができないため、Silverlightではこの機能はサポートされていません。


モジュールのロード



一度ModuleCatalog



フル、モジュールがロードおよび初期化する準備ができています。モジュールをロードすると、モジュールのアセンブリがディスクからメモリにロードされます。アセンブリがディスク上にない場合、最初に別のソースから取得する必要があります。この例は、Silverlight .xap



ファイルを使用してインターネットからアセンブリをダウンロードすることです。ModuleManager



初期化および読み込みプロセスの調整を担当します。



モジュールの初期化



モジュールをロードした後、それらは初期化されます。これは、モジュールクラスのインスタンスが作成され、そのメソッドがInitialize



呼び出されることを意味します初期化は、モジュールがアプリケーションに統合される場所です。モジュールを初期化するときは、次のオプションを考慮してください。







モジュールは他のモジュールに依存する場合があります。場合はモジュールAが依存するモジュールBモジュールBは、前に初期化されなければならないモジュールAModuleManager



これらの依存関係を監視し、正しい順序でモジュールを初期化します。モジュールカタログの定義方法に応じて、コード、構成、またはXAMLでモジュールの依存関係を定義できます。



コードでの依存関係の定義


コードでモジュールを登録するか、フォルダーでそれらを見つけるWPFアプリケーションの場合、Prismは、次の例に示すように、モジュールクラスの宣言属性を提供します。



 [Module(ModuleName = "ModuleA")] [ModuleDependency("ModuleD")] public class ModuleA: IModule { ... }
      
      





XAMLでの依存関係の定義


以下のXAMLショーモジュールFが依存するモジュールE



 <Modularity:ModuleInfo Ref="ModuleF.xap" ModuleName="ModuleF" ModuleType="ModuleF.ModuleF, ModuleF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" > <Modularity:ModuleInfo.DependsOn> <sys:String>ModuleE</sys:String> </Modularity:ModuleInfo.DependsOn> </Modularity:ModuleInfo>
      
      





構成ファイルでの依存関係の定義


次の例は、そのファイルApp.configファイルを示しているモジュールDは、依存モジュールBを



 <modules> <module assemblyFile="Modules/ModuleD.dll" moduleType="ModuleD.ModuleD, ModuleD" moduleName="ModuleD"> <dependencies> <dependency moduleName="ModuleB"/> </dependencies> </module>
      
      





モジュールのオンデマンド読み込み



オンデマンドでロードモジュールに、あなたは彼らが設定modulesディレクトリオプションにロードする必要があることを指定する必要がありますInitializationMode



OnDemand



その後、モジュールのロードを要求するコードをアプリケーションに追加する必要があります。



コードでのオンデマンドロードジョブ


モジュールが属性を介してオンデマンドでロードする必要があるという決定を次の例に示します。



 protected override void ConfigureModuleCatalog() { Type moduleCType = typeof(ModuleC); this.ModuleCatalog.AddModule(new ModuleInfo() { ModuleName = moduleCType.Name, ModuleType = moduleCType.AssemblyQualifiedName, InitializationMode = InitializationMode.OnDemand }); }
      
      





XAMLのオンデマンドダウンロードジョブ


InitializationMode.OnDemand



次のコード例に示すように、XAMLでモジュールディレクトリを定義するタイミングを決定できます



 ... <Modularity:ModuleInfoGroup InitializationMode="OnDemand"> <Modularity:ModuleInfo Ref="ModuleE.xap" ModuleName="ModuleE" ModuleType="ModuleE.ModuleE, ModuleE, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> ...
      
      





構成ファイルのオンデマンドロードジョブ


次のコード例に示すように、InitializationMode.OnDemand



ファイルでモジュールのディレクトリをいつ指定するかを決定できますApp.config







 ... <module assemblyFile="Modules/ModuleC.dll" moduleType="ModuleC.ModuleC, ModuleC" moduleName="ModuleC" startupLoaded="false"/> ....
      
      





モジュールダウンロードリクエスト


モジュールがオンデマンドでダウンロード可能であると判断された後、アプリケーションはダウンロードを要求できます。ダウンロードを開始するコードはIModuleManager



、ローダーによってコンテナに登録されたサービスへのリンクを取得する必要があります



 private void OnLoadModuleCClick(object sender, RoutedEventArgs e) { moduleManager.LoadModule("ModuleC"); }
      
      





バックグラウンドでのモジュールのリモート読み込み



アプリケーションの起動後、またはユーザーが必要な場合にのみ、モジュールをバックグラウンドでダウンロードすると、アプリケーションの起動時間を短縮できます。



リモートブート用のモジュールの準備


Silverlightアプリケーションでは、モジュールは.xap



ファイルにパッケージ化されます。モジュールをアプリケーションとは別にダウンロードするには、別の.xap



ファイルを作成します。.xap



各.xapファイルのサイズと引き換えにダウンロード要求の数を最適化するために、単一のファイルに複数のモジュールを配置することができます。

ご注意

.xapファイルごとに、新しいSilverlightアプリケーションプロジェクトを作成する必要があります。Visual Studio 2008および2010では、アプリケーションプロジェクトのみが個別の.xap



ファイルを生成します。これらのプロジェクトにはApp.xaml



ファイルやファイルは必要ありませんMainPage.xaml





ダウンロード追跡


このクラスModuleManager



は、モジュールのロードの進行状況を追跡するイベントを提供します。アップロードされたバイト数と全負荷サイズを提供して、進行状況の割合を取得します。これを使用して、ダウンロードの進行状況を視覚的に表示できます。



 this.moduleManager.ModuleDownloadProgressChanged += this.ModuleManager_ModuleDownloadProgressChanged;
      
      





 void ModuleManager_ModuleDownloadProgressChanged(object sender, ModuleDownloadProgressChangedEventArgs e) { ... }
      
      





モジュールがロードされたことを確認する



このサービスModuleManager



は、モジュールがロードされたとき、またはロードできないときに追跡するイベントを提供します。



 this.moduleManager.LoadModuleCompleted += this.ModuleManager_LoadModuleCompleted;
      
      





 void ModuleManager_LoadModuleCompleted(object sender, LoadModuleCompletedEventArgs e) { ... }
      
      





アプリケーションとモジュールの疎結合を維持するには、このイベントを使用してモジュールをアプリケーションに統合しないようにする必要があります。代わりにモジュールメソッドを使用してくださいInitialize







LoadModuleCompletedEventArgs



プロパティが含まれていますIsErrorHandled



モジュールがロードに失敗し、アプリケーションがModuleManager



エラーの報告を防ぎ例外をスローしたい場合、このプロパティをに設定する必要がありますtrue





ご注意

モジュールをロードして初期化した後、モジュールアセンブリをアンロードすることはできません。モジュールインスタンスへの参照はPrismライブラリによって保存されないため、初期化の完了後にモジュールクラスのインスタンスをガベージコレクションできます。


MEFのモジュール



このセクションでは、MEFを依存性注入コンテナーとして使用する場合の違いのみを強調します。

ご注意

MEFをMefBootstrapper



使用する場合、を使用しMefModuleManager



ます。新しいタイプがMEFによってインポートされたときに更新されるようにModuleManager



、インターフェイスIPartImportsSatisfiedNotification



拡張および実装しますModuleCatalog





MEFを使用してモジュールをコードに登録する


MEFを使用する場合、ModuleExport



MEFが自動的にそれらを検出できるように、モジュールクラスに属性適用できます



 [ModuleExport(typeof(ModuleB))] public class ModuleB : IModule { ... }
      
      





また、MEFをAssemblyCatalog



使用して、アセンブリ内のエクスポートされたすべてのモジュールクラスの検出に使用できるクラスAggregateCatalog



と、複数のディレクトリを単一の論理ディレクトリにマージできるクラス使用して、モジュールを検出およびロードできますデフォルトでは、クラスMefBootstrapper



はインスタンスを作成しますAggregateCatalog



メソッドConfigureAggregateCatalog



オーバーライドして、アセンブリを登録できます



 protected override void ConfigureAggregateCatalog() { base.ConfigureAggregateCatalog(); // Module A        . this.AggregateCatalog.Catalogs.Add( new AssemblyCatalog(typeof(ModuleA).Assembly)); this.AggregateCatalog.Catalogs.Add( new AssemblyCatalog(typeof(ModuleC).Assembly)); }
      
      





プリズムの実装では、MefModuleManager



同期化AggregateCatalog



MEFとプリズムをModuleCatalog



従ってプリズムによって書かれたモジュール、検出可能、ModuleCatalog



またはAggregateCatalog





ご注意

MEFは Lazy, Value



.






MEFを使用してローカルディレクトリでモジュールを検出する


MEFは、DirectoryCatalog



モジュール(およびその他のエクスポートされたMEFタイプ)を含むアセンブリのフォルダーを表示するために使用できるクラス提供します。この場合、メソッドConfigureAggregateCatalog



オーバーライドしてディレクトリを登録します。このアプローチはWPFでのみ使用できます。



このアプローチを使用するにModuleExport



は、次の例に示すように、最初に属性を使用してモジュール名とその依存関係を指定する必要があります



 protected override void ConfigureAggregateCatalog() { base.ConfigureAggregateCatalog(); DirectoryCatalog catalog = new DirectoryCatalog("DirectoryModules"); this.AggregateCatalog.Catalogs.Add(catalog); }
      
      





MEFを使用したコードの依存関係の定義


WPFアプリケーションの場合、次のように属性ModuleExport



使用します



 [ModuleExport(typeof(ModuleA), DependsOnModuleNames = new string[] { "ModuleD" })] public class ModuleA : IModule { ... }
      
      





MEF , . MEF ModuleCatalog



, , ModuleCatalog



, XAML ( - ). ModuleCatalog



MEF, ModuleCatalog



, DependsOnModuleNames



. MEF ModuleCatalog



Silverlight, XAP.



MEF


MEF ModuleExport



, , InitializationMode



, , , .



 [ModuleExport(typeof(ModuleC), InitializationMode = InitializationMode.OnDemand)] public class ModuleC : IModule { ... }
      
      





MEF


, Prism, MEF, MEF DeploymentCatalog



, .xap



.xap . MefXapModuleTypeLoader



DeploymentCatalog



AggregateCatalog



.



.xap



, . , , . Microsoft.Practices.Prism.MefExtensions.dll



.



, DLL 'Copy Local'=false



. .xap . .xap . , , , .xap , , .xap .





アセンブリキャッシュの詳細については、MSDNの「方法:アセンブリライブラリキャッシュを使用する」を参照してください 。http://msdn.microsoft.com/en-us/library/dd833069( VS.95).aspx



モジュラーの詳細Prismの原則として、MEF for WPF QuickStartまたはModularity with Unity for WPF QuickStartを参照してください。クイックスタートの詳細については、WPFのモジュール方式のクイックスタートを参照してください



モジュラーアプリケーションの構築に使用されるPrismライブラリ関数については、「Prismの拡張」の「モジュール」を参照してください



All Articles