目次
モジュラーアプリケーションは、単一のユニットに統合できる多くの機能ブロック(モジュール)に分割できるアプリケーションです。 クライアントモジュールは、アプリケーションの機能全体の一部をカプセル化し、通常、相互接続された機能部分の集合です。 これには、ユーザーインターフェイスやビジネスロジックなどのアプリケーション機能などの関連コンポーネントのセット、またはロギング用のアプリケーションレベルサービス、ユーザー認証および承認などのアプリケーションインフラストラクチャの一部が含まれる場合があります。 モジュールは互いに独立していますが、疎結合の方法で相互に対話できます。 モジュラーアプリケーションは、アプリケーションの開発、テスト、展開、および拡張を促進できます。
たとえば、パーソナルバンキングアプリケーションを考えてみましょう。 ユーザーは、アカウント間での送金、請求書の支払い、単一のユーザーインターフェイス(UI)を使用した個人データの更新など、多くの機能にアクセスできます。 ただし、これらの各機能は個別のモジュールにカプセル化されています。 これらのモジュールは相互に通信し、データベースサーバーやWebサービスなどのバックエンドシステムとも通信します。 アプリケーションサービスは、さまざまなモジュールのそれぞれにさまざまなコンポーネントを統合し、ユーザーとの対話を処理します。 ユーザーには、唯一の完全なアプリケーションのように見える統合ビューが表示されます。
次の図は、モジュラーアプリケーションの設計を示しています。

モジュラーアプリケーションを構築する利点
おそらく、アセンブリ、インターフェイス、クラス、および優れたオブジェクト指向開発原則を使用して、適切に設計されたアプリケーションをすでに作成しているでしょう。 この場合、深刻な対策を講じないと、アプリケーションの設計は「モノリシック」のままになります(すべての機能がアプリケーション内で強力に接続された方法で実装されます)。
一方、アプリケーションを構築するためのモジュラーアプローチは、大規模な機能領域を分離し、それらを独立して開発またはテストするのに役立ちます。 これにより、開発とテストが簡単になり、アプリケーションが将来より柔軟で簡単に拡張できるようになります。 モジュール方式の利点は、アプリケーションを管理しやすい部分に分割することにより、アプリケーションアーキテクチャをより柔軟で保守しやすくすることができることです。 各部分は特定の機能をカプセル化し、明確ではあるが疎結合のチャネルを介して統合します。
モジュラーアプリケーション開発のためのPrismサポート
Prismは、実行時にモジュール式アプリケーションを開発し、モジュールを管理するのに役立ちます。 Prism機能を使用すると、モジュラーアプリケーションを構築するために独自のプラットフォームを実装およびテストする必要がないため、時間を節約できます。 Prismは、モジュラーアプリケーションを開発するために次の機能をサポートしています。
- 名前付きモジュールを登録したり、その場所を決定したりするためのモジュールのカタログ。 次の方法でモジュールカタログを作成できます。
- コードまたはXAMLでモジュールを定義します。
- WPFの場合:この方法では、モジュールをディレクトリに配置することにより、中央ディレクトリに明示的に定義せずにすべてのモジュールをロードできます。
ご注意
このアプローチを使用すると、モジュールを含むアセンブリはプロジェクトのアセンブル時に自動的にコンパイルされず、プロジェクトの実行可能ファイルからのリンクがないため、出力ディレクトリにコピーされない場合があります。
- WPFの場合:構成ファイルでモジュールを定義します。
- 初期化モードと依存性注入の決定に使用されるモジュールの属性を宣言的に設定します。
- モジュール間の弱い接続を維持するための依存性注入コンテナーとの統合。
- モジュールをロードするには:
- モジュールが正しい順序でロードされ、モジュールが一度だけロードおよび初期化されるようにするための、複製およびループ検出を含む依存関係管理。
- モジュールのバックグラウンドロードとオンデマンドロードにより、アプリケーションの起動時間を最小限に抑えます。 残りのモジュールは、バックグラウンドで、または必要に応じてロードおよび初期化できます。
基本的な概念
このセクションでは、
IModule
、モジュールのロードプロセス、モジュールカタログ、モジュール間の通信の維持、および依存性注入コンテナーなど、Prismのモジュール方式に関連する基本概念を説明します。
IModule :モジュラーアプリケーションのビルディングブロック
モジュールは、1つの場所に集められた機能コンポーネントとリソースの論理セットです。 モジュールは、個別に開発、テスト、デプロイ、およびアプリケーションに統合できます。 パッケージには、1つ以上のアセンブリを含めることができます。これらのアセンブリは、個別に配置することも、単一のXAPファイルにアセンブルすることもできます。 各モジュールには、モジュール機能を初期化してアプリケーションに統合する中心的なクラスがあります。 このクラスは、
IModule
実装し
IModule
。 パッケージをモジュールとして識別するには、
IModule
を実装するクラスがあれば十分です。
IModule
は、
Initialize
メソッドが1つあります。このメソッド内で、モジュール機能を初期化してアプリケーションに統合するために必要なロジックを実装できます。 モジュールの目的に応じて、ユーザーインターフェイスの領域に表現を登録したり、アプリケーションで追加のサービスを利用可能にしたり、機能を拡張したりできます。 次のコードは、モジュールの最小実装を示しています。
public class MyModule : IModule { public void Initialize() { // . } }
ご注意
IModule
によって提供される初期化メカニズムを使用する代わりに、 Stock Trader RIは、ビュー、サービス、およびタイプを登録するための宣言型の属性ベースのアプローチを使用します。
モジュールの寿命
Prismのモジュールロードプロセスには次のものが含まれます。
- モジュールの登録/発見。 特定のアプリケーションの実行時にロードされるモジュールは、モジュールディレクトリで定義されます。 ディレクトリには、ロードされたモジュール、その場所、およびロードされる順序に関する情報が含まれています。
- モジュールをロードしています。 モジュールを含むアセンブリがメモリにロードされます。 このフェーズでは、ネットワークから、または別のリモートロケーションまたはローカルディレクトリからモジュールをダウンロードする必要があります。
- モジュールの初期化。 モジュールクラスを作成し、
IModule
介してInitialize
メソッドをIModule
。
次の図は、モジュールのロードプロセスを示しています。

モジュールカタログ
ModuleCatalog
は、アプリケーションが使用できるモジュールに関する情報が含まれています。 ディレクトリは、本質的に
ModuleInfo
クラスのコレクションです。 各モジュールは、モジュールの名前、タイプ、および場所を格納する
ModuleInfo
クラスによって記述されます。
ModuleCatalog
に
ModuleCatalog
インスタンスを
ModuleCatalog
するためのいくつかの典型的なアプローチがあります。
- コード内のモジュールの登録。
- XAMLでモジュールを登録します。
- 構成ファイルへのモジュールの登録(WPFのみ)。
- ディスク上のローカルディレクトリ内のモジュールの検出(WPFのみ)。
使用する登録および検出メカニズムの選択は、アプリケーションに必要なものによって異なります。 構成ファイルまたはXAMLファイルを使用すると、アプリケーションはモジュール参照を保存できません。 ローカルディレクトリを使用すると、アプリケーションでモジュールを検出できますが、ファイルで定義する必要はありません。
モジュールのロード時間の管理
Prismアプリケーションは、可能な限り早くモジュールを初期化することができます。これは、利用可能な場合、またはアプリケーションが必要とする場合、オンデマンドとして知られています。 Silverlightアプリケーションの場合、モジュールはアプリケーションと共にロードすることも、アプリケーションの起動後にバックグラウンドでロードすることもできます。 次のモジュールのロード手順を考慮してください。
- アプリケーションが機能するために必要なモジュールは、アプリケーションとともにロードされ、起動時に初期化される必要があります。
- アプリケーションの通常の使用中にほとんど常に使用される関数を含むモジュールは、バックグラウンドでロードされ、使用可能になったときに初期化できます。
- めったに使用されない(または他のモジュールが依存する可能性のあるモジュールをサポートする)関数を含むモジュールは、バックグラウンドでロードし、オンデマンドで初期化できます。
アプリケーションの分割方法、一般的なユースケース、アプリケーションの起動速度、ダウンロードの数とサイズを考慮して、モジュールのロードと初期化を構成する方法を決定します。
モジュールとアプリケーションの統合
Prismは、アプリケーションのロードに必要な
UnityBootstrapper
および
MefBootstrapper
クラスを提供します。 これらのクラスを使用して、モジュールの検出とロードに必要なモジュールマネージャーを作成および構成できます。 モジュールカタログの構成方法をオーバーライドして、XAMLファイル、構成ファイルで定義されたモジュールを登録したり、ディレクトリの場所を指定したりできます。
モジュールの
Initialize
メソッドを使用して、モジュールをアプリケーションの他の部分と統合します。 これを行う方法は、アプリケーションの構造とモジュールの内容によって異なります。 以下は、モジュールをアプリケーションに統合するために必要な一般的な手順です。
- モジュールに含まれるビューをアプリケーションのナビゲーション構造に追加します。 これは、検出またはビューの挿入を使用して複合アプリケーションのUIを作成するときの一般的な手順です。
- アプリケーションまたはサービスレベルのイベントをサブスクライブします。
- アプリケーション依存性注入コンテナに共有サービスを登録します。
モジュール間の通信
モジュールが疎結合されるべきであることを考慮しても、それらは互いにデータとメッセージを交換する傾向があります。 疎結合システムにはいくつかの通信パターンがあり、それぞれに長所と短所があります。 原則として、これらのパターンの組み合わせが最終的に使用されます。 これらのパターンの一部を次に示します。
- 大まかに関連するイベント。 モジュールは、特定のイベントが発生したことをブロードキャストできます。 他のモジュールは、そのようなイベントを受信するためにサブスクライブできます。 このようにして、このイベントが発生すると通知されます。 疎結合イベントは、モジュール間の通信を確立するためのかなり簡単な方法です。 この点で、簡単に実装できます。 ただし、イベントに依存しすぎるプロジェクトは、特に多くのイベントがある場合、または単一のタスクを達成するために一緒に編成する必要がある場合、サポートが難しくなる可能性があります。 この場合、共有サービスの使用はより合理的かもしれません。
- 共有サービス 共有サービスは、共通のインターフェースを介してアクセスできるクラスであり、通常はコンテナーを介して解決されます。 通常、共有サービスは共有アセンブリに存在し、認証、ログ、構成などのシステム全体のサービスを提供します。 このようなサービスは、多くの場合シングルトーンです。
- 共有リソース。 モジュールが互いに直接通信したくない場合は、データベースや多数のWebサービスなどの共有リソースを介してモジュールを間接的に通信させることができます。
依存性注入とモジュラーアプリケーション
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関数の使用をサポートしています。
- モジュールタイプとXAPファイルの場所との関連付け。
- XAMLおよびWPFおよびSilverlightのコードでモジュールを登録します。
- WPFの構成ファイルおよびスキャンされたディレクトリを介したモジュールの登録。
- モジュールのロードステータスの追跡。
- モジュールのカスタム宣言メタデータ。
重要な決定
最初に決定する必要があるのは、モジュラーアプリケーションを開発するかどうかです。 前のセクションで説明したように、モジュール式アプリケーションを構築することには多くの利点がありますが、これらの利点を得るために追加の時間と労力が必要です。 それでもモジュール式アプリケーションを開発することに決めた場合は、さらに考慮すべきことがいくつかあります。
- 使用するプラットフォームを特定します。 独自のモジュラープラットフォームを作成し、Prism、MEF、または別のプラットフォームを使用できます。
- アプリケーションの編成方法を決定します。 どのモジュールが各モジュールの一部であるかなど、各モジュールの境界を定義することにより、モジュールアーキテクチャに近づきます。 開発を容易にするため、アプリケーションのデプロイ方法を制御するため、またはプラガブルまたは拡張可能なアーキテクチャをサポートするために、モジュール方式の原則を使用することを決定できます。
- モジュールの分割方法を決定します。 モジュールは、要件に基づいて、たとえば機能分野、提供されたモジュール、開発チーム、展開要件などに基づいて分割できます。
- アプリケーションがすべてのモジュールに提供する基本サービスを定義します。 たとえば、エラー報告サービス、認証および許可サービスなどです。
- Prismを使用する場合は、モジュールをモジュールディレクトリに登録する方法を決定します。 WPFの場合、コード、XAML、構成ファイルにモジュールを登録するか、ディスク上のローカルディレクトリにモジュール検出を構成できます。 Silverlightの場合、コードまたはXAMLでモジュールを登録できます。
- モジュール間でデータと依存関係を転送するための戦略を定義します。 モジュールは互いに通信する必要があり、モジュール間の依存関係を処理する必要があります。
- 依存性注入コンテナを定義します。 通常、モジュラーシステムでは、疎結合、動的ロード、およびモジュール作成を提供するために、依存関係の注入、制御の反転、またはサービスロケーターが必要です。 Prismでは、Unity、MEF、または別のコンテナを選択でき、UnityまたはMEFに基づいたアプリケーション用のライブラリを提供します。
- アプリケーションの起動時間を最小限にします。 アプリケーションの起動時間を最小限に抑えるために、モジュールをオンデマンドでロードし、バックグラウンドでロードすることを検討してください。
- 展開要件を定義します。 アプリケーションをどのようにデプロイするかを考える必要があります。 これは、XAPファイルで収集されるアセンブリの数に影響する場合があります。 Prismなどの共有ライブラリを分割して、Silverlightにキャッシュされたアセンブリを使用することもできます。
次のセクションでは、これらのソリューションについて詳しく説明します。
アプリケーションのモジュールへの分離
モジュール方式でアプリケーションを開発する場合、個別に開発、テスト、および展開できる個別のクライアントモジュールに構造化します。 各モジュールは、アプリケーションの全機能の一部をカプセル化します。 最初に行う必要のある設計上の決定の1つは、アプリケーションの機能を個別のモジュールに分離する方法を決定することです。
モジュールは、一連の関連する機能をカプセル化し、一連の異なる責任を負う必要があります。 モジュールは、アプリケーションの垂直セクションまたはサービスの水平レイヤーを表すことができます。 大規模なアプリケーションには、両方のタイプのモジュールがあります。


大規模なアプリケーションでは、モジュールを垂直スライスと水平レイヤーの両方に編成できます。 たとえば、モジュールには次のものが含まれます。
- Stock Trader Reference Implementation(Stock Trader RI)のニュースモジュールなど、特定のアプリケーション機能を含むモジュール。
- 購入、請求、総勘定元帳など、多数の関連する使用セクションの特定のサブシステムまたは機能を含むモジュール。
- ジャーナリング、キャッシュ、承認サービスなどのインフラストラクチャサービス、またはWebサービスを含むモジュール。
- 他の内部システムに加えて、Siebel CRMやSAPなどの基幹業務(LOB)システムを呼び出すサービスを含むモジュール。
モジュールには、他のモジュールに対する最小限の依存関係セットが必要です。 モジュールが別のモジュールに依存している場合、特定のタイプではなく、共有ライブラリで定義されたインターフェイスを介して、または
EventAggregator
を使用してイベントを介して他のモジュールと通信することにより、モジュールに疎接続する必要があります。
モジュール方式の原則の目的は、機能や技術が追加および削除された場合でも、柔軟で保守しやすく、安定するようにアプリケーションを分割することです。 これを実現する最良の方法は、モジュールが可能な限り独立し、明確に定義されたインターフェースを持ち、可能な限り分離されるようにアプリケーションを開発することです。
プロジェクトとモジュールの比率を決定する
モジュールを作成してパッケージ化する方法はいくつかあります。 推奨される最も一般的な方法は、モジュールごとに1つのアセンブリを作成することです。 これにより、モジュールを論理的に分離し、適切なカプセル化を促進できます。 また、アセンブリをモジュールとして、またはその逆について話すこともできます。 ただし、単一のアセンブリに複数のモジュールが含まれることを妨げるものはありません。場合によっては、ソリューション内のプロジェクトの数を最小限に抑えることが望ましい場合があります。 大規模なアプリケーションには、10〜50個のモジュールがあります。 各モジュールを独自のプロジェクトに転送すると、ソリューションが複雑になり、Visual Studioのパフォーマンスが低下する可能性があります。 プロジェクトまたはアセンブリごとに1つのモジュールに固執したい場合、モジュールまたはモジュールのセットを独自のソリューションに分割することが理にかなっている場合があります。
XAPおよびモジュールファクタリング
Silverlightアプリケーションの場合、モジュールは通常、個別のXAPファイルにパッケージ化されますが、場合によっては、XAPに複数のモジュールがある場合があります。 アプリケーションの実行と新しいオプションの有効化に必要なダウンロードリクエストの数とサイズを最小限に抑えるために必要なXAPファイルの数を検討します。 各モジュールを独自のプロジェクト/アセンブリに分離する場合は、各アセンブリに独自のXAPを展開用に挿入するか、複数のアセンブリを単一のXAPに含めるかを決定する必要があります。
単一のXAPファイルに複数のモジュールを含めるか分割するかの選択に影響するいくつかの要因:
- ダウンロードサイズと共有依存関係。 各XAPファイルには、その宣言と.zipパッケージにわずかな余分なサイズのオーバーヘッドがあります。 さらに、モジュール間に共通の依存関係があり、依存モジュールまたはキャッシュライブラリに属していない場合、各XAPにはこれらの依存ライブラリが含まれるため、負荷サイズが大幅に増加する可能性があります。
- アプリケーションで複数のモジュールが必要な場合の同期。 アプリケーションの起動時にビューを提供するなど、複数のモジュールを同時にロードして使用する場合、それらを単一のXAPファイルにパックすると、ダウンロードが少し速くなり、両方のモジュールがクライアントから同時に物理的にアクセス可能になります。 Prismのモジュール機能は、依存関係を指すモジュールが正しい順序でロードされるようにします。 ただし、ダウンロードの合計サイズが同じであっても、1つではなく2つのダウンロードを作成する場合、わずかなパフォーマンスのオーバーヘッドが発生します。
- バージョン管理モジュール。 異なるモジュールが独立したタイムラインで開発され、潜在的に個別に展開される場合、それらを別々のXAPに配置して、異なるバージョンでよりきれいにマークし、独立して更新できるようにすることができます。
各XAPで同じアセンブリを複数回ロードしないようにするには、次の2つのアプローチを使用できます。
- 共有依存関係を別のインフラストラクチャモジュールに拡張し、この共有モジュールの依存関係を使用する消耗品モジュールを用意します。
- Silverlightのアセンブリライブラリキャッシュを使用して、Prismモジュールローダーではなく、Silverlightによって一度読み込まれ、キャッシュされる共有ライブラリに共有タイプを配置します。
依存性注入を使用して疎結合を実現する
モジュールは、ホストアプリケーションまたは他のモジュールによって提供されるコンポーネントとサービスに依存する場合があります。Prismは、モジュール間の依存関係を登録して、正しい順序でロードおよび初期化する機能をサポートしています。Prismは、ロード後のモジュールの初期化もサポートしています。初期化中に、モジュールは、必要な追加のコンポーネントおよびサービスへのリンクを受信したり、他のモジュールで使用できるようにするために含まれるコンポーネントおよびサービスを登録したりできます。
モジュールは、特定のタイプを直接作成する代わりに、独立したメカニズムを使用して外部インターフェイスのインスタンスを取得する必要があります。彼は、依存性注入コンテナまたはファクトリサービスを通じてこれを行うことができます。 UnityやMEFなどの依存性注入コンテナーを使用すると、型は依存性注入によってインターフェイスインスタンスを自動的に取得できます。 PrismはUnityとMEFの両方と統合して、モジュールが依存性注入メカニズムを簡単に使用できるようにします。
次の図は、コンポーネントおよびサービスへのリンクを取得または登録するために必要なモジュールをロードする一般的なプロセスを示しています。

この例では、アセンブリ
OrdersModule
はクラスを定義します
OrdersRepository
(順序機能を実装する他のビューおよびクラスとともに)。アセンブリ
CustomerModule
は、サービスによって提供されるインターフェイスに基づくクラス
CustomersViewModel
に依存するクラスを定義
OrdersRepository
します。アプリケーションとダウンロードプロセスの起動には、次の手順が含まれます。
- ブートストラップはモジュールの初期化プロセスを開始し、モジュールローダーはをロードして初期化します
OrdersModule
。 - 初期化フェーズ
OrdersModule
でOrdersRepository
は、コンテナに登録します。 - モジュールローダーがロードされます
CustomersModule
。モジュールの読み込み順序は、メタデータに基づいて決定できます。 -
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
呼び出されることを意味します。初期化は、モジュールがアプリケーションに統合される場所です。モジュールを初期化するときは、次のオプションを考慮してください。
- . , , .
- . / , .
Initialize
, . , , , . , . ,MenuService
( ),Initialize
– , .
ご注意
. ,Initialize
, . , . , , , «» . - . , Unity MEF, . , .
モジュールは他のモジュールに依存する場合があります。場合はモジュールAが依存するモジュールB、モジュールBは、前に初期化されなければならないモジュールA。
ModuleManager
これらの依存関係を監視し、正しい順序でモジュールを初期化します。モジュールカタログの定義方法に応じて、コード、構成、または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 , . MEFModuleCatalog
, ,ModuleCatalog
, XAML ( - ).ModuleCatalog
MEF,ModuleCatalog
,DependsOnModuleNames
. MEFModuleCatalog
Silverlight, XAP.
MEF
MEFModuleExport
, ,InitializationMode
, , , .
[ModuleExport(typeof(ModuleC), InitializationMode = InitializationMode.OnDemand)] public class ModuleC : IModule { ... }
MEF
, Prism, MEF, MEFDeploymentCatalog
,.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の拡張」の「モジュール」を参照してください。