原文
モジュール・アプリケーションは、より大規模なアプリケーションに統合することができる、対となる疎く結合した機能単位に分割されているアプリケーションです (名前を付けたモジュール)。クライアント・モジュールは一部のアプリケーションの全体的な機能をカプセル化して、一般的に対となる関連した関係を示します。 それは、ユーザー・インターフェイスとビジネス・ロジックやアプリケーション基盤構造の一部が含まれているアプリケーション機能のような、 ログを記録するためのアプリケーション・レベルのサービスや認証しているユーザーのような、関連したコンポーネントのコレクションを含むことができます。モジュールは、 相互に独立していますが、疎く結合したやり方で、互いに情報交換することができます。 モジュール・アプリケーション設計を使用することで、あなたのアプリケーションを開発して、テストして、 配布して、保持することをあなたのためのより簡単に作成します。
例えば、個人的な銀行業務アプリケーションを考えてみます。 ユーザーは、いろいろな機能にアクセスすることができます。このようなアカウントの間で、お金を転送する、 請求を支払い、一つのユーザー・インターフェイス(UI)から個人性情報を更新するように、 しかしながら、背後で、これらの機能の各々は、別々のモジュールの中でカプセル化されます。 これらのモジュールは、互いに、そして、データベースサーバとWebサービスのような、バックエンドシステムと情報交換します。 アプリケーションサービスは、それぞれの異なるモジュールの中に、様々なコンポーネントを統合し、そして、ユーザーとの通信を処理します。 ユーザーは、一つのアプリケーションのように見える、統合ビューを見ています。
次の図は、複数のモジュールとモジュール・アプリケーションのデザインを示しています。
モジュール構成
モジュール・アプリケーションを構築する利点
Benefits of Building Modular Applications
あなたは、おそらく、これまでに、アセンブリ、インターフェースとクラス、そして、優れたオブジェクト指向設計の原則を使用して、 上手に設計されたアプリケーションを構築しています。それにしても、細心の注意が取られない限り、 あなたのアプリケーション設計は、まだ「モノリシックである」場合があります。 (すべての機能は、アプリケーション内のどこかで密接に結びついた方法で実装されています)、 それは、アプリケーションを難しく開発、テスト、拡張、保守するために、作成することができます。
モジュール・アプリケーション・アプローチ、一方で、あなたのアプリケーションの大規模な機能領域を識別することで、 あなたを助けることができます。 そして、あなたが、独立してその機能を開発し、そして、テストすることができます。これは、より簡単に、開発とテストを作成することができます。 しかし、また、それは、あなたのアプリケーションを、将来、より柔軟に、そして、より簡単に拡張するために、作成することができます。 モジュール化による方法の利点は、それが、あなたの全体的なアプリケーション・アーキテクチャを、より柔軟で保守しやすく作成できることです。 なぜなら、それは、あなたのアプリケーションを、扱いやすい断片に破壊することができます。それぞれの断片は、特定の機能をカプセル化します。 そして、それぞれの断片は、明確な、しかし、疎く結合した通信回線で統合されます。
モジュール・アプリケーション開発のためのPrismのサポート
Prism's Support for Modular Application Development
Prismは、あなたのアプリケーションの、モジュール・アプリケーション開発のためのサポートと実行時の管理モジュールを提供します。 Prismのモジュール開発機能を使用することで、あなたの時間を節約することができます。 あなたが、あなた独自のモジュラー性フレームワークの実装とテストをする必要がないため、 Prismは、次のモジュール・アプリケーションの開発機能をサポートしています。:
- 登録のためのモジュール・カタログは、モジュールとそれぞれのモジュールの場所に名をつけます。;
あなたは、次に示す方法で、モジュール・カタログを作成することができます。:
- コードやExtensible Application Markup Language (XAML)でモジュールを定義することで、
- ディレクトリでモジュールを発見することによって、それで、あなたは、明示的に定義することなく、 統合されたカタログで、すべてのあなたのモジュールを読み込むことができます。
- 設定ファイルでモジュールを定義することによって、
- モジュールのための宣言型のメタデータの属性は、初期化モードと依存関係をサポートします。
- 依存性注入コンテナとの統合により、モジュール間の疎結合をサポートします
- モジュールを読み込むために:
- 依存関係の管理、モジュールが正しい順序で読み込まれることを確実に行うために、 2重化とサイクル検出が含まれています。そして、一度だけ、読み込まれ、初期化されます。
- アプリケーションの起動時間を最小限にするモジュールのオンデマンドとバックグラウンド・ダウンロード; 残りのモジュールは、バックグラウンドで、あるいは、それらが必要とされるとき、読み込まれ、初期化されることができます。
中心的な概念
Core Concepts
IModule:モジュール・アプリケーションの構成単位
IModule: The Building Block of Modular Applications
モジュールは、機能とリソースの論理的なコレクションです。これは、ある意味、パッケージ化されています。 それは、アプリケーションに、別々に、開発し、テストし、配布し、統合することができます。パッケージは、1つ以上のアセンブリであることができます。 それぞれのモジュールは、モジュールを初期化し、そして、アプリケーションに、その機能を統合するための役割を果たす中心となるクラスを持っています。 そのクラスは、IModuleインターフェイスを実装しています。
備考
IModuleインターフェイスを実装するクラスの存在は、モジュールとして、パッケージを識別するのに十分です。
IModuleインターフェイスには、Initializeという名前の、一つのメソッドがあります。 その中で、あなたは、アプリケーションに、モジュールの機能を初期化と統合することが必要な、どんなロジックでも実装できます。 モジュールの目的に応じて、それは、複数の要素で構成されたユーザー・インターフェイスに、ビューを登録することができます。 アプリケーションが利用できる追加のサービスを作成します。 あるいは、アプリケーションの機能を拡張します。次のコードは、モジュールの最低限の実装を示しています。
public class MyModule : IModule
{
public void Initialize()
{
// Do something here.
// ここで何かします。
}
}
備考
IModuleインターフェイスで、提供される初期化の仕組みを使用する代わりに、 株トレーダーRIは、宣言、登録するビューための属性に基づくアプローチ、サービスと型を使用します。
モジュールの寿命
Module Lifetime
Prism内で、モジュールを読み込んでいるプロセスは、次のものが含まれています。:
- モジュールの登録/発見
- 読み込まれるモジュール
- モジュールを初期化すること
特定のアプリケーションのための実行時に読み込まれるモジュールは、Moduleカタログで定義されています。 カタログには、読み込まれるモジュールに関するそれらの場所と順序に関する情報が含まれています。ここで、それらはロードされます。
モジュールが含まれるアセンブリは、メモリに読み込まれます。 この段階は、いくつかの遠隔地またはローカル・ディレクトリから取得することをモジュールに要求するかもしれません。
モジュールは、続いて、初期化されます。モジュール・クラスの作成されるインスタンスを示しています。 そして、IModuleインタフェースを通じて、それらのInitializeメソッドを呼び出します。
次に示す図は、モジュールを読み込んでいるプロセスを示しています。
モジュール読み込んでいるプロセス
モジュールのカタログ
Module Catalog
ModuleCatalogは、アプリケーションによって使用することができる、モジュールに関する情報を格納しています。 カタログは、本質的には、ModuleInfoクラスのコレクションです。それぞれのモジュールは、 モジュールの他の属性の間の名前、型と場所を記録する、ModuleInfoクラスで記述されています。 ModuleCatalogをModuleInfoインスタンスに書き込むには、いくつかの代表的な方法があります。:
- コード内のモジュールを登録する
- XAML内のモジュールを登録する
- 設定ファイル内のモジュールを登録する
- ディスク上のローカル・ディレクトリでモジュールを発見する
あなたが、使用する必要がある、登録と発見の仕組みは、あなたのアプリケーションが必要とするものに依存しています。 設定ファイルやXAMLファイルを使用することは、あなたのアプリケーションが、モジュールへの参照の必要をなくすことができます。 ディレクトリを使用することは、ファイルでそれらを指定することなく、アプリケーションが、モジュールを発見することができます。
いつモジュールを読み込むか制御する
Controlling When to Load a Module
Prismアプリケーションは、「利用可能な時」と知られているように、 あるいは、「オンデマンド」として知られているように、アプリケーションがそれらを必要とするとき、 可能な限り早くモジュールを初期化することができます。 モジュールをロードするために、以下のガイドラインを考えて見てください。:
- アプリケーションが実行される時、アプリケーションを実行するために必要なモジュールは、 アプリケーションで読み込まれ、初期化されている必要があります。
- 機能が含まれているモジュールは、それらが利用可能になるとき、たいてい、代表的な使い方で使用されるアプリケーションは、 バックグラウンドで読み込まれ、そして、初期化されていることができます。
- めったに使用されない機能が含まれるモジュール(あるいは、他のモジュールが必要に応じて依存するモジュールをサポートします)。 オンデマンドで、読み込まれ、初期化されていることができます。
あなたが、あなたのモジュールを、ダウンロードし、初期化するために、どのように、設定するか判断するために、 あなたのアプリケーション、一般的に使用される筋書き、アプリケーション起動時間とダウンロードの数とサイズを、どのように、分割しているか考えてみてください。
統合されたモジュールとアプリケーション
Integrate Modules with the Application
Prismは、あなたのアプリケーションを起動する次のクラスを提供します。:UnityBootstrapperやMefBootstrapper。 これらのクラスは、モジュールを発見して、ロードするために、モジュール・マネージャを作成して、設定するために使用することができます。 あなたは、数行のコードで、XAMLファイル、設定ファイルやディレクトリの場所で、指定されるモジュールを登録するために、設定メソッドを上書きすることができます。
残りのアプリケーションでモジュールを統合するために、モジュールInitializeメソッドを使用します。 この変化する、あなた行う方法は、あなたのアプリケーションとモジュールの内容の構造に依存します。 以下は、あなたのアプリケーションに、あなたのモジュールを統合するために、一般的な行なう必要があることです。:
- アプリケーションのナビゲーション構造に、モジュールのビューを追加します。ビュー発見やビュー注入を使用して、 複数の要素で構成されたUIのアプリケーションを構築するとき、これは、一般的です。
- アプリケーションレベルのイベントやサービスに登録します。
- アプリケーションの依存関係注入コンテナで共有サービスを登録します。
モジュール間の通信
Communicate Between Modules
モジュールは、相互に、弱い結合を持つ必要がありますが、モジュールが互いに、情報をやりとりすることは一般的です。 各々それら独自の強さで、いくつかの疎く結合した通信パターンがあります。 一般的に、これらのパターンの組合せは、結果として得られる解決法を作成するために使用されます。 以下は、これらのパターンのいくつかを紹介します。:
- 疎く結合したイベント
- 共有サービス
- 共用リソース
モジュールは、確実にイベントが発生したことを、くまなく伝えることができます。他のモジュールは、イベントが発生するとき、 それらが通知されるように、それらのイベントに登録することができます。疎く結合したイベントは、2つモジュールの間で通信を設定する軽量な方法です。; その結果、それらは、簡単に実装されます。しかしながら、あまりに大量のイベントに頼るデザインは、保守するのが難しくなります。 特に、多くのイベントが、単一タスクを成し遂げるために、互いに組織化されている必要がある場合、 その場合、共有サービスを検討したほうが良いかもしれません。
共有サービスは、一般的なインターフェースによってアクセスすることができるクラスです。 一般的に、共有サービスは共用アセンブリに存在し、認証、ログの記録、や設定のような、システム全体のサービスを提供します。
あなたが、モジュールが互いに、直接、情報のやりとりしたくない場合、また、あなたは、データベースや対となるWebサービスのように、 共用リソースを通じて、それらに、間接的に情報をやりとりしてもらうことができます。
依存関係注入とモジュール・アプリケーション
Dependency Injection and Modular Applications
Unityアプリケーション・ブロック(Unity)のようなコンテナ、そして、Managed Add-in Framework(MAF)は、 あなたが、簡単に、疎く結合したやり方で、コンポーネントを構成することを助けるパワフルなデザインパターンの反転制御(IoC)と依存関係注入を使用することができます。 それは、コンポーネントが、参照をハードコードすることに依存せずに、他のコンポーネントの参照を取得することができます。 それによって、望ましいコードの再利用と柔軟性の向上を促進します。依存関係注入は、疎く結合した、モジュール・アプリケーションを構築するとき、 極めて役に立ちます。Prismは、アプリケーション内のコンポーネントを構成するために使用される、依存関係注入コンテナを選ばないように設計されています。 コンテナは、ご自由にお選びください。そして、主にあなたのアプリケーションの要件と選択によってきまります。 しかしながら、Microsoftから、考慮するための2つの主要な依存関係の注入フレームワークが、あるでしょうか?UnityとMEF。
パターンと実践Unityアプリケーション・ブロックは、依存関係注入コンテナの完全な機能を提供します。 それは、プロパティに基づいて、そして、コンストラクタに基づいて、なたが、コンポーネントの間で透過的な注入動作と方針ができる注入と注入方針をサポートします。 ;また、それは、依存関係注入コンテナで一般的な、他の機能の格納をサポートします。
MEF(は、.NET Framework 4.5の一部です)は、依存関係注入をサポートすることによって、 拡張可能な.NETアプリケーションを構築するためのサポートを提供します。-コンポーネントの構成に基づいて、 他の機能を提供します。それは、モジュール・アプリケーション開発をサポートしています。 それは、アプリケーションが実行時に、コンポーネントを発見すること、そして、疎く結合した方法でアプリケーションにそれらのコンポーネントを統合することができます。 MEFは、素晴らしい拡張性と構成のフレームワークです。それには、アセンブリと型の発見、 型の依存関係ソリューション、依存関係注入といくつかの素晴らしいアセンブリ・ダウンロード機能が含まれています。 次に示すものと同様に、Prismは、MEF機能を利用することをサポートしています。:
- XAMLとコード属性を通してのモジュール登録
- 設定ファイルとディレクトリ走査を通してのモジュール登録
- モジュールが、読み込まれるような、状態の追跡
- MEFを使用する際のモジュールのための、ユーザー定義した宣言型のメタデータ
UnityとMEF依存関係注入コンテナの両方は、Prismで継ぎ目なく動作します。
重要な決定事項
Key Decisions
あなたが、行うと思われる最初の決定は、あなたが、モジュール・ソリューションを開発したいかには、関係ありません。 先のセクションで説明された、モジュール・アプリケーションを構築することは、多くの利点がありますが、 あなたが、これらの利点を獲得するために必要な時間と労力に関係があります。 あなたが、モジュールの解決案を開発することに決める場合、考慮するいくつかのことがあります。:
- あなたが、使用するフレームワークを決定します。
- あなたのソリューションを、どのように系統化するかを決定します。
- あなたのモジュールを、どのように分割するかを決定します。
- アプリケーションが、決定する中心となるサービスを、すべてのモジュールに提供するでしょう。
- あなたが、Prismを使用している場合、モジュール・カタログで、モジュールを登録するために、あなたが使用する方法を決定します。
- あなたの依存関係注入コンテナを決定します。
- アプリケーションの起動時間を最小にする
- 配布要件の決定
あなたは、Prism、MEFや他のフレームワークを使用する、あなた独自のモジュール型のフレームワークを作成することができます。
それぞれのモジュールの境界を定義するモジュラアーキテクチャの方法に含まれているアセンブリは、それぞれのモジュールの一部です。 アプリケーションが、どのように配布されるか、制御を終了することと同じように、あるいは、プラグインや拡張可能なアーキテクチャをサポートしたい場合、 あなたは、開発を容易にするために、モジュールを使用することに決めることができます。
例えば、機能分野、プロバイダー・モジュール、開発チームと配布要件によって、モジュールは、要件に基づいて、それぞれに分割することができます。
1つの例は、中心となるサービスで、障害報告サービスや認証と認可サービスができるかもしれません。
WPFのために、あなたは、コード、XAML、設定ファイルや発見されているモジュール、ディスクのローカル・ディレクトリの中でモジュールを登録することができます。 あなたのモジュールの情報のやり取りと依存関係についての戦略を決定します。 モジュールは、互いに情報をやりとりする必要があるでしょう。そして、あなたは、モジュール間で依存関係を扱う必要があります。
一般的に、モジュラーシステムは、疎結合とダイナミックローディングとモジュールの作成を提供するために、依存関係の注入、コントロールの反転やサービス・ロケーターを必要とします。 Prismは、UnityやMEFに基づくアプリケーションのために、Unity、MEFや他のコンテナ、そして、提供されるライブラリを使用して、選択を提供します。
アプリケーションの起動時間を最小限にするために、モジュールの要求とバックグラウンドのダウンロードについて考えます。
あなたは、あなたが、アプリケーションをどのように配布するか考える必要があります。
次の項目では、これらの決定のいくらかについて、内容を提供します。
あなたのApplicationをモジュールに分割する
Partition Your Application into Modules
あなたが、モジュール化の手法で、アプリケーションを開発するとき、あなたは、アプリケーションを、個別に開発、テスト、配布することができる、 別々のクライアント・モジュールに構築します。それぞれのモジュールは、あなたのアプリケーションの全体的な機能の一部をカプセル化するでしょう。 あなたが、作成する必要のある最初の設計上の決定の1つは、アプリケーションの機能をモジュールに、どのように、分割するか決定することです。
モジュールは、対となる関連する関係をカプセル化する必要があります。そして、対となる異なった責任を持ちます。 モジュールは、アプリケーションの垂直の一部や水平サービス層を示すことができます。大規模なアプリケーションは、両方の型のモジュールを持っているでしょう。
垂直の一部のまわりで、モジュールとアプリケーションは、系統化されます。
水平層のまわりで、モジュールとアプリケーションは、系統化されます。 より大規模なアプリケーションは、モジュールを垂直の一部と水平層で系統化されるかもしれません。モジュールのいくつかの例には、次のものが含まれています。:
- モジュールは、株トレーダーの参考になる実装のニュース・モジュールのような、(株トレーダーRI)特定のアプリケーションの機能が含まれています。
- モジュールには、対となる関連した使用事例のための、購買、請求書や総勘定元帳を発行することのような、特定のサブシステムや機能が含まれています。
- モジュールには、ログの記録、貯蔵と認可サービスやWebサービスのような、基盤構造サービスが含まれています。
- モジュールには、他の内部システムに加えて、Siebel CRMとSAPのような、基幹業務(LOB)システムを呼び出すサービスが含まれています。
モジュールは、他のモジュールで、依存関係の最低限のまとまりを備えている必要があります。モジュールが、他のモジュールで依存関係を持っている場合、 それは、具体的な型の代わりに、共用ライブラリで定義されるインターフェースを使用して、あるいは、EventAggregatorイベント型を通じて、 他のモジュールと情報をやりとりするために、EventAggregatorを使用して、疎く結合している必要があります。
モジュール方式の目標は、このような方法で、機能と技術は追加され、除去されるように、柔軟で、保守しやすく、 安定なまま、アプリケーションを分割することです。これを達成する最も良い方法は、モジュールが、可能な限り独立する、 そして、可能な限り分離するように、うまく定義されたインターフェースを持ってる、あなたのアプリケーションを設計することです。
プロジェクトをモジュール化する比率を決定する
Determine Ratio of Projects to Modules
モジュールを作成して、パッケージ化するためのいくつかの方法があります。推薦される最も一般的な方法は、 モジュールにつき、一つのアセンブリを作成することです。これは論理モジュールを分離しておくのを助け、厳密なカプセル化を促進します。 あなたが、モジュールを配布する方法をパッケージ化することと同じように、また、それは、より簡単に、アセンブリについて話すための、モジュール境界として、作成します。 しかしながら、何も一つのアセンブリに複数のモジュールが含まれることを妨げません。そして、場合によっては、 これは、あなたのソリューションで、プロジェクトの数を最小限にするのを好まれるかもしれません。大規模なアプリケーションのため、10-50のモジュールを持つことは、珍しくありません。 それ自身のプロジェクトに、それぞれのモジュールを分離することは、ソリューションに、多くの複雑さを追加します。 そして、Visual Studioの処理能力を低下させることができます。あなたが、アセンブリ/Visual Studioプロジェクトことに、1つのモジュールにくっつける選択する場合、時には、 それは、モジュールやモジュールのまとまりを、これを管理する、それら独自のソリューションに分割する意味があります。
疎結合のために、依存関係注入を使用する
Use Dependency Injection for Loose Coupling
モジュールは、ホスト・アプリケーションで、あるいは、他のモジュールで、提供されるコンポーネントとサービスに依存するかもしれません。 Prismは、モジュール間で、それらが、正しい順序で、読み込まれて、初期化されるように、依存関係を登録する機能をサポートします。 また、Prismは、モジュールの初期化をサポートしています。それらが、アプリケーションに読み込まれるとき、モジュールの初期化の間、モジュールは、 それが必要とする追加されたコンポーネントとサービスに、参照を取り出すことができます。 そして、あるいは、どんなコンポーネントとサービスでも、登録します。それは、他のモジュールが利用できるように、それらを作成するために、含まれています。
例えば、依存関係注入コンテナやファクトリー・サービスを使用して、モジュールは、直接、具体的な型のインスタンスを生成しているディレクトリの代わりに、 外部インタフェースのインスタンスを取得するために、独立した仕組みを使用する必要があります。UnityやMEFのような依存関係注入コンテナは、 自動的にインターフェースのインスタンスと型を取得するために、型を提供します。 それは、依存関係注入を通す必要があります。Prismは、依存関係注入のモジュールを簡単にを使用するために、UnityとMEFを一緒に統合します。
次の図表は、操作の代表的な流れを示しています。モジュールが、読み込まれるとき、 それは、コンポーネントとサービスに、参照を取得する、あるいは、登録するために必要です。
依存関係の注入の例
この例では、OrdersModuleアセンブリは、OrdersRepositoryクラスを定義します。(それは、他のビューとクラスと一緒に、命令機能を実装します)。 CustomerModuleアセンブリは、OrdersRepositoryに依存する、CustomersViewModelクラスを定義します。 一般的に、サービスによって公開されるインターフェースに基づいています。アプリケーションの起動と起動するプロセスは、次に示す手順が含まれています。:
- ブートストラッパーは、モジュールの初期化行程を開始します。そして、モジュール・ローダーは、OrdersModuleを読み込んで、初期化します。
- OrdersModuleの初期化では、それは、コンテナでOrdersRepositoryを登録します。
- モジュール・ローダーは、続いて、CustomersModuleを読み込みます。モジュールを読み込む順序は、モジュール・メタデータ内の依存関係で指定することができます。
- CustomersModuleは、コンテナを通して、それ解決することによって、CustomerViewModelのインスタンスを構築します。 CustomerViewModelは、OrdersRepository上で依存関係を持っています。(一般的に、そのインターフェースに基づいています)、 そして、コンストラクタやプロパティ注入を通して、それを示します。コンテナは、OrdersModuleによって登録される型で、View Modelの構築に基づいて、その依存関係を注入します。 最終結果は、それらのクラスの間の密結合なしで、CustomerViewModelからOrderRepositoryへのインターフェース参照です。
備考
OrderRespository(IOrderRepository)を露出させるために使用するインターフェースは、 別々の「共有サービス」アセンブリや「命令サービス」アセンブリに存在させることができます。それらのサービスを公開するために、サービス・インターフェースと要求される型だけが、含まれています。 この方法では、強い依存関係が、CustomersModuleとOrdersModuleの間にありません。
両方のモジュールが、依存関係注入コンテナで、暗黙的な依存関係を持っていることに注意してください。 この依存関係は、モジュール・ローダーで、モジュール構築の間に注入されます。
中心となる筋書き
Core Scenarios
あなたのアプリケーションで、モジュールで動作するとき、この項目は、あなたが遭遇する一般的な筋書きを説明します。 これらの筋書きは、モジュールが、すでに読み込まれていることを検出する時、モジュールを定義、モジュールの登録と発見、モジュールの読み込み、 モジュールの初期化、モジュールの依存関係の指定、要求に応じたモジュールの読み込み、背後でのリモートモジュールをダウンロードと検出が含まれています。 XAMLやアプリケーション設定ファイルで、あるいは、ローカル・ディレクトリを探査することで、あなたは、コードの中で、モジュールを登録し、発見することができます。
モジュールの定義
Defining a Module
モジュールは、アプリケーションに、別々に、開発し、テストし、配布し、統合することができる方法で、 パッケージ化された機能の論理コレクションとリソースです。それぞれのモジュールは、モジュールを初期化し、 そして、アプリケーションに、その機能を統合するための役割を果たす中心となるクラスを持っています。 ここに、示されるように、クラスは、IModuleインターフェイスを実装しています。:
public class MyModule : IModule
{
public void Initialize()
{
// Initialize module
// 初期化モジュール
}
}
あなたが、Initializeメソッドを実装する方法は、あなたのアプリケーションの要件に依存しています。 モジュール・クラス型、初期化モードと、どんなモジュール依存関係でも、モジュール・カタログで定義されています。 カタログのそれぞれのモジュールのために、モジュール・ローダーは、モジュール・クラスのインスタンスを作成します。 そして、それは、Initializeメソッドを呼び出します。モジュールは、モジュール・カタログで指定された順番で処理されます。 モジュールが、ダウンロードされ、利用でき、そして、依存関係が満足するとき、ランタイムの初期化順序に基づきます。
あなたのアプリケーションが使用している、モジュール・カタログの種類に応じて、モジュール依存関係は、 モジュール・クラスそれ自身の宣言型の属性によって、あるいは、モジュール・カタログ・ファイルの範囲内で、 どちらでも設定できます。次のセクションでは、より多くの内容を提供します。
モジュールを登録し、発見する
Registering and Discovering Modules
アプリケーションが読み込むことができるモジュールは、モジュール・カタログで定義されています。 Prismのモジュール・ローダーは、決定するために、モジュール・カタログを使用します。 モジュールは、そのアプリケーションに読み込まれ、利用できます。 それらを読み込むとき、そして、ここで、それらは、順番に読み込まれます。
モジュール・カタログは、IModuleCatalogインターフェースを実装するクラスによって表示されます。 モジュール・カタログ・クラスは、アプリケーション初期化の間、アプリケーション・ブートストラッパー・クラスによって作成されます。 Prismは、あなたが選択するモジュール・カタログの異なる実装を提供します。また、あなたは、AddModuleメソッドを呼び出すことによって、 あるいは、カスタマイズされた動作で、モジュール・カタログを作成するために、 ModuleCatalogから派生することで、他のデータ・ソースからモジュール・カタログを埋め込むことができます。
備考
一般的に、Prismのモジュールは、 モジュールの初期化のために必要な型のインスタンスを取り出すために、依存関係注入コンテナと一般的なサービス・ロケーターを使用しています。 UnityとMEFコンテナは、Prismでサポートされています。モジュールを登録し、発見し、ダウンロードし、初期化する全体的なプロセスは、同じものですが、 内容は、UnityやMEFが使用されているかどうかに基づいて、異なっています。 方法の間のコンテナ固有の違いは、この項目を通して説明されます。
コード内のモジュールを登録する
Registering Modules in Code
ほとんどの基本的なモジュール・カタログは、ModuleCatalogクラスによって、提供されます。 あなたは、モジュール・クラス型を指定することによって、 プログラム上で、モジュールを登録するこのモジュール・カタログを使用することができます。 また、あなたは、モジュール名と初期化モードを、プログラム上で指定することができます。ModuleCatalogクラスで、 モジュール・ディレクトリを登録するために、あなたのアプリケーションのブートストラッパー・クラスで、 AddModuleメソッドを呼び出します。例は、次のコードで示されます。
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基底クラスは、ModuleCatalogの作成を支援するために、CreateModuleCatalogメソッドを提供します。 既定では、このメソッドは、ModuleCatalogインスタンスを作成します。 しかし、このメソッドは、モジュール・カタログの異なる型を作成するために、派生クラスで上書きすることができます。
XAMLファイルを使用しているモジュールの登録
Registering Modules Using a XAML File
あなたは、XAMLファイルでそれを指定することによって、宣言的にモジュール・カタログを定義することができます。 XAMLファイルが、どんな種類のモジュール・カタログ・クラスを作成するか、そして、どのモジュールを追加するか指定します。 通常、.xamlファイルは、あなたのシェル・プロジェクトへのリソースとして追加されています。 モジュール・カタログは、ブートストラッパーとCreateFromXamlメソッドの呼び出しで作成されます。 技術的な観点から、XAMLファイルが、インスタンスを生成するオブジェクトの階層を簡単に定義するため、 この方法は、コード内で、ModuleCatalogを定義することに、極めてよく似ています。
次のコードの例は、モジュール・カタログを指定しているXAMLファイルを示しています。
<!-- ModulesCatalog.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="file://DirectoryModules/ModularityWithMef.Desktop.ModuleB.dll" InitializationMode="WhenAvailable">
<Modularity:ModuleInfo ModuleName="ModuleB" ModuleType="ModularityWithMef.Desktop.ModuleB, ModularityWithMef.Desktop.ModuleB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</Modularity:ModuleInfoGroup>
<Modularity:ModuleInfoGroup InitializationMode="OnDemand">
<Modularity:ModuleInfo Ref="file://ModularityWithMef.Desktop.ModuleE.dll" ModuleName="ModuleE" ModuleType="ModularityWithMef.Desktop.ModuleE, ModularityWithMef.Desktop.ModuleE, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Modularity:ModuleInfo Ref="file://ModularityWithMef.Desktop.ModuleF.dll" ModuleName="ModuleF" ModuleType="ModularityWithMef.Desktop.ModuleF, ModularityWithMef.Desktop.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>
<!-- Module info without a group グループ情報のないモジュール->
<Modularity:ModuleInfo Ref="file://DirectoryModules/ModularityWithMef.Desktop.ModuleD.dll" ModuleName="ModuleD" ModuleType="ModularityWithMef.Desktop.ModuleD, ModularityWithMef.Desktop.ModuleD, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</Modularity:ModuleCatalog>
備考
ModuleInfoGroupsは、同じアセンブリ内にあり、 同じように初期化される、モジュールをグループ化するための便利な方法を提供します。 あるいは、同じグループ内のモジュールで、依存関係を持っているだけです。 モジュール間の依存関係は、同じModuleInfoGroup内のモジュールの内で定義することができます。; しかしながら、あなたは、異なるModuleInfoGroups内のモジュールの間で、依存関係を定義することができません。 モジュールをモジュール・グループに配置することは、選択可能です。 グループのために設定されるプロパティは、そのすべてが含まれたモジュールに適用されるでしょう。 また、モジュールが、グループ内になくても登録できることに注意します。
あなたのアプリケーションのブートストラッパー・クラスでは、次のコードで示すように、 あなたは、XAMLファイルは、あなたのModuleCatalogのためのソースで、指定する必要があります。
protected override IModuleCatalog CreateModuleCatalog()
{
return ModuleCatalog.CreateFromXaml(new Uri("/MyProject;component/ModulesCatalog.xaml", UriKind.Relative));
}
設定ファイルを使用してモジュールを登録する
Registering Modules Using a Configuration File
WPFでは、App.configファイルで、モジュール情報を指定することができます。この方法の利点は、 このファイルがアプリケーションにコンパイルされないということです。 これは極めて簡単に、アプリケーションを再コンパイルせずに、実行時に、それをモジュールに追加し、除去できます。
次のコードの例は、モジュール・カタログを指定している設定ファイルを示しています。 あなたが、自動的に、モジュールが読み込まれることを望む場合、startupLoaded="true"を設定します。
<!-- ModularityWithUnity.Desktop\app.config -->
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="modules" type="Microsoft.Practices.Prism.Modularity.ModulesConfigurationSection, Microsoft.Practices.Prism"/>
</configSections>
<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>
</configuration>
備考
たとえ、あなたのアセンブリが、グローバル・アセンブリ・キャッシュに、 あるいは、アプリケーションとして、同じフォルダの中にあるとしても、assemblyFile属性は必要です。 属性は、適切なIModuleTypeLoaderにmoduleTypeを、マッピングするために使用されます。
あなたのアプリケーションのブートストラッパー・クラスでは、あなたは、設定ファイルが、 あなたのModuleCatalogのためのソースであることを指定する必要があります。これを実行するには、 あなたは、次のコードの示される、ConfigurationModuleCatalogクラスを使用します。
protected override IModuleCatalog CreateModuleCatalog()
{
return new ConfigurationModuleCatalog();
}
備考
あなたは、今まで通り、コードの中で、ConfigurationModuleCatalogにモジュールを追加することができます。 あなたは、例えば、あなたのアプリケーションが、機能するために絶対に必要なカタログで定義されたモジュールを確認するために、これを使用することができます。
ディレクトリでモジュールを見つける
Discovering Modules in a Directory
PrismのDirectoryModuleCatalogクラスは、あなたが、ローカル・ディレクトリを指定することができます。 WPFのモジュール・カタログとして、このモジュール・カタログは、あなたのアプリケーションのためのモジュールを定義する、 指定されたフォルダを走査し、アセンブリを探します。この方法を使用するために、 あなたは、モジュール名とそれらが持っているどんな依存関係でも指定するために、 あなたのモジュール・クラス上で、宣言型の属性を使用する必要があるでしょう。 次に示すコードの例は、モジュール・カタログを示しています。 それは、ディレクトリ内のアセンブリを発見することにより埋め込まれます。
モジュールを読み込む
Loading Modules
ModuleCatalogが埋め込まれたあと、モジュールは、読み込まれて、初期化される準備ができています。 モジュールの読み込みは、モジュールアセンブリが、ディスクからメモリに移動することを示しています。 ModuleManagerは、読み込みと初期化プロセスを調整する責任があります。
モジュールを初期化する
Initializing Modules
モジュールが、読み込まれた後、それらは初期化されます。 これは、モジュール・クラスのインスタンスが、作成され、そして、そのInitializeメソッドが、呼び出されることを示しています。 初期化は、モジュールとアプリケーションを統合するための場所です。 モジュールの初期化のための次の可能性を考慮してください。:
- アプリケーションで、モジュールのビューを登録します。
- アプリケーションレベルのイベントやサービスに登録します。
あなたのモジュールが、ビュー発見やビュー注入を使用して、ユーザー・インターフェイス(UI)の構成に関与している場合、 あなたのモジュールは、適切な領域名で、そのViewやView Modelを関連付ける必要があるでしょう。 これは、アプリケーション内で、ビューを動的に、メニュー、ツールバーや他の視覚的な領域に表示することができます。
多くの場合、アプリケーションは、あなたのモジュールが、興味があるアプリケーション固有のサービスそして、あるいは、イベントを公開します。 それらのアプリケーション・レベルのイベントとサービスに、モジュールの機能を追加するために、Initializeメソッドを使用します。
例えば、アプリケーションは、それがシャットダウンしているとき、イベントを呼び出すかもしれません。 そして、あなたのモジュールは、そのイベントに反応したがっています。それは、あなたのモジュールが、 アプリケーション層サービスに、いくつかのデータを提供する必要があることもできます。 例えば、あなたが、MenuServiceを作成した場合、(それは、メニュー項目を追加し、削除する責任があります)、 モジュールのInitializeメソッドは、あなたが、正しいメニュー項目を追加する場所です。
備考
モジュール・インスタンスの寿命は、規定では短命です。Initializeメソッドが、 読み込みプロセスの間に呼び出されたあと、モジュール・インスタンスへの参照は、解放されます。 あなたが、モジュール・インスタンスに、強い参照チェーンを確立ていない場合、それは、ガベージコレクトされるでしょう。
この動作は、デバッグするために、問題になるかもしれません。あなたが、イベントに登録する場合、 あなたのモジュールへ、弱い参照を格納します。 なぜなら、ガーベジコレクタが、実行されると、あなたのモジュールは、単純に「見えなく」なります。
- 依存関係注入コンテナと型を登録します。
あなたが、UnityやMEFのような、依存関係注入パターンを使用している場合、 モジュールは、使用するためのアプリケーションや他のモジュールのために型を登録するかもしれません。 また、それは、必要とする型のインスタンスを解決するために、コンテナを要求するかもしれません。
モジュールの依存関係を指定する
Specifying Module Dependencies
モジュールは、他のモジュールに依存するかもしれません。モジュールAが、モジュールBに依存する場合、 モジュールBは、モジュールAの前に初期化する必要があります。ModuleManagerは、これらの依存関係を追跡し続け、 それに対応してモジュールを初期化します。あなたが、モジュール・カタログを定義した方法に依存します。 あなたは、コード、設定やXAMLで、あなたのモジュールの依存関係を定義することができます。
コード内で、依存関係を指定する
Specifying Dependencies in Code
次のコードの例に示すように、モジュールをコードに登録するWPFアプリケーションやディレクトリで、 モジュールを発見するために、Prismは、モジュールを作成するとき、使用する宣言型の属性を提供します。
// (when using Unity)
[Module(ModuleName = "ModuleA")]
[ModuleDependency("ModuleD")]
public class ModuleA: IModule
{
...
}
XAMLで依存関係を指定します
Specify Dependencies in XAML
次のXAMLは、モジュールFがモジュールEに依存する場所を示します。
<!-- ModulesCatalog.xaml -->
<Modularity:ModuleInfo Ref="file://ModularityWithMef.Desktop.ModuleE.dll" moduleName="ModuleE" moduleType="ModularityWithMef.Desktop.ModuleE, ModularityWithMef.Desktop.ModuleE, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<Modularity:ModuleInfo Ref="file://ModularityWithMef.Desktop.ModuleF.dll" moduleName="ModuleF" moduleType="ModularityWithMef.Desktop.ModuleF, ModularityWithMef.Desktop.ModuleF, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" >
<Modularity:ModuleInfo.DependsOn>
<sys:String>ModuleE</sys:String>
</Modularity:ModuleInfo.DependsOn>
</Modularity:ModuleInfo>
. . .
設定で依存関係を指定します
Specify Dependencies in Configuration
次の例では、App.configファイルは、モジュールFがモジュールEに依存する場所を示します。
<!-- App.config -->
<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>
要求に応じてモジュールを読み込む
Loading Modules on Demand
要求されるモジュールを読み込むために、あなたは、指定する必要があります。 それらは、InitializationModeをOnDemandに設定し、モジュール・カタログに読み込まれている必要があります。あなたが、それを実行したあと、 あなたは、あなたのアプリケーションに、モジュールが読み込まれるという要望をコードに記述する必要があります。
コードの要求に応じて読み込みを指定する
Specifying On-Demand Loading in Code
モジュールは、要求に応じて、属性を使用して指定されたあと、次のコードの例に示すように、
// Boostrapper.cs
protected override void ConfigureModuleCatalog()
{
. . .
Type moduleCType = typeof(ModuleC);
this.ModuleCatalog.AddModule(new ModuleInfo()
{
ModuleName = moduleCType.Name,
ModuleType = moduleCType.AssemblyQualifiedName,
InitializationMode = InitializationMode.OnDemand
});
. . .
}
XAMLの要求に応じて読み込みを指定する
あなたが、App.configファイル内の、あなたのモジュール・カタログを定義するとき、次のコードの例に示すように 、あなたは、InitializationMode.OnDemandを指定することができます。
<!-- ModulesCatalog.xaml -->
...
<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" />
...
モジュールがいつ読み込まれたか検出する
Detecting When a Module Has Been Loaded
モジュールが読み込まれる、読み込うぃ失敗する時、ModuleManagerサービスは、追跡するために、アプリケーションのためのイベントを提供します。 あなたは、IModuleManagerインターフェースの依存関係注入を通じて、このサービスへの参照を取得することができます。
this.moduleManager.LoadModuleCompleted += this.ModuleManager_LoadModuleCompleted;
void ModuleManager_LoadModuleCompleted(object sender, LoadModuleCompletedEventArgs e)
{
...
}
アプリケーションとモジュールを疎く結合し続けるために、 アプリケーションは、アプリケーションでモジュールを統合するために、このイベントを使用することを避ける必要があります。 その代わりに、モジュールのInitializeメソッドは、アプリケーションで統合する処理をする必要があります。
LoadModuleCompletedEventArgsには、IsErrorHandledプロパティが含まれています。モジュールが、読み込みに失敗し、 そして、アプリケーションが必要とする場合、ModuleManagerがエラーを記録する、 そして、例外を投げることを防ぐために、それは、このプロパティを、trueに設定することができます。
備考
モジュールが読み込まれて、初期化されたあと、モジュールアセンブリをアンロードできません。 モジュール・インスタンスの参照は、Prismライブラリで、格納されていません。 それで、モジュール・クラスインスタンスは、初期化が完了していたあと、ガーベージとして集められます。
MEFのモジュール
Modules in MEF
この項目は、あなたが、依存関係注入コンテナとして、MEFを使用することを選択する場合、 違いをただ強調します。
備考
MEFを使用するとき、MefModuleManagerは、MefBootstrapperによって使用されます。新しい型が、MEFでインポートされるとき、 ModuleCatalogが更新されることを確実とするために、ModuleManagerを拡張し、IPartImportsSatisfiedNotificationインターフェースを実装します。
MEFを使用して、コード内のモジュールを登録する
Registering Modules in Code Using MEF
MEFを使用するとき、あなたは、ModuleExport属性を、MEFに、自動的に型を発見させるために、モジュール・クラスに適用することができます。以下は一例です。
[ModuleExport(typeof(ModuleB), InitializationMode = InitializationMode.OnDemand)]
public class ModuleB : IModule
{
...
}
また、あなたは、AssemblyCatalogクラスを使用して、MEFを発見するために、モジュールを読み込むために、 使用することができます。それは、アセンブリ内の、すべてのエクスポートされたモジュール・クラスを発見するために、使用し続けることができます。 そして、AggregateCatalogクラスは、複数のカタログを1つの論理的カタログに結合することができます。 既定では、PrismのMefBootstrapperクラスは、AggregateCatalogインスタンスを作成します。 次のコードの例に示すように、あなたは、続いて、アセンブリを登録するために、 ConfigureAggregateCatalogメソッドを上書きすることができます。
protected override void ConfigureAggregateCatalog()
{
base.ConfigureAggregateCatalog();
// Module A is referenced in in the project and directly in code.
// モジュールAは、コードの中で、プロジェクトとディレクトリで、参照されます。
this.AggregateCatalog.Catalogs.Add(
new AssemblyCatalog(typeof(ModuleA).Assembly));
this.AggregateCatalog.Catalogs.Add(
new AssemblyCatalog(typeof(ModuleC).Assembly));
. . .
}
PrismのMefModuleManagerの実装は、MEFのAggregateCatalogとPrismのModuleCatalogの同期を維持します。 それによって、Prismは、ModuleCatalogやAggregateCatalogを通して、追加されるモジュールを発見することができます。
備考
MEFは、Valueプロパティが使用されるまで、エクスポートされた、
そして、インポートされた型のインスタンス生成を防ぐために、広範囲にわたり、Lazy
MEFを使用しているディレクトリでモジュールを発見する
Discovering Modules in a Directory Using MEF
MEFは、DirectoryCatalogを提供します。 それは、モジュールが含まれているアセンブリのためのディレクトリを調べるために使用することができます。 (そして、他のMEFは、型をエクスポートしました)。 この場合、あなたは、ディレクトリを登録するために、ConfigureAggregateCatalogメソッドを上書きします。 このアプローチは、WPFでのみ、利用できます。
この方法を使用するために、あなたは、最初に、ModuleExport属性を使用している、 あなたのモジュールに、モジュール名と依存関係を適用する必要があります。 次のコードの例に示すように、これは、MEFが、モジュールをインポートできます。そして、Prismが、 更新されたModuleCatalogを維持することができます。
protected override void ConfigureAggregateCatalog()
{
base.ConfigureAggregateCatalog();
. . .
DirectoryCatalog catalog = new DirectoryCatalog("DirectoryModules");
this.AggregateCatalog.Catalogs.Add(catalog);
}
MEFを使用するコード内の依存関係を指定する
Specifying Dependencies in Code Using MEF
MEFを使用するWPFアプリケーションのために、ここで示されるように、ModuleExport属性を使用します。
// (when using MEF)
[ModuleExport(typeof(ModuleA), DependsOnModuleNames = new string[] { "ModuleD" })]
public class ModuleA : IModule
{
...
}
MEFは、実行時に、モジュールを発見することができるため、 また、あなたは、実行時に、モジュールの間で新しい依存関係を発見するかもしれません。 あなたは、ModuleCatalogと一緒にMEFを使うことができますが、それが、XAMLや設定から読み込まれるとき、 そのModuleCatalogは、依存関係チェーンを検証することを覚えておくことは重要です。 (どんなモジュールでも読み込まれる前に)。モジュールが、ModuleCatalog内で一覧を示され、 続いて、MEFを使用して読み込まれる場合、ModuleCatalog依存関係は使用されるでしょう。 そして、DependsOnModuleNames属性は無視されるでしょう。
MEFを使用して、要求に応じて読み込みを指定する
Specifying On-Demand Loading Using MEF
あなたが、モジュールとモジュール依存関係を指定するための、MEFとModuleExport属性を使用している場合、 ここに、示されるように、あなたは、指定するために、モジュールは、要請に応じて読み込まれる必要がある、 InitializationModeプロパティを使用することができます。:
[ModuleExport(typeof(ModuleC), InitializationMode = InitializationMode.OnDemand)]
public class ModuleC : IModule
{
}
詳細情報
More Information
あるいは、アセンブリキャッシュの詳細については、「どのように:MSDNの上でAssembly Library Cachingを使用します(原文リンク)」を参照してください。
Prismのモジュラー性をさらに知るためには、WPFのクイックスタートのための、モジュラー性とMEF、あるいは、WPFのクイックスタートのための、 モジュラー性とUnityを参照してください。クイックスタートの詳細については、 モジュールのクイックスタート(原文リンク) を参照してください。
モジュール機能に関する情報は、Prismライブラリで拡張することができます。 モジュール(原文リンク)については、 Prismライブラリを拡張する(原文リンク)を参照してください。