Home > C# > Toolkit > UIパターン > Prism > ドキュメント

15: Prism Library 5.0 for WPFを拡張する

新規作成日 2016-07-01
最終更新日

15: Extending the Prism Library 5.0 for WPF(原文)

Microsoft Prism Library 5.0 for WPFの開発者のガイドから

Prismには、Windows Presentation Foundation (WPF)クライアント開発のための推奨された実践を表示する資産が含まれています。 開発者は、Model-View-ViewModel(MVVM)パターンを使用して、複合アプリケーションを作成する、ガイダンスの変更されていないバージョンを使用できます。 しかしながら、各々のアプリケーションが、一意であるため、あなたは、あなたの個々の必要性のために、Prismが、適切か分析する必要があります。 場合によっては、あなたは、あなたの企業に、最も良い実行を組み込むために、ガイダンスをカスタマイズしたいと思うでしょう。そして、頻繁に開発者の作業を繰り返します。

Prismライブラリは、あなたのWPFクライアント・アプリケーションのために、基盤の役割を果たします。 Prism Libraryは、重要な部分がカスタマイズする事ができるように、設計されました。 あるいは、あなたの固有のシナリオに合わせるために置き換えます。 あなたは、新しい機能を組み込むために、既存のライブラリのためのソース・コードを変更することができます。 開発者は、配置するコンテナに対する依存のため、それら独自のデザインのもので、アーキテクチャ内の重要なコンポーネントを置き換えることができます。 [そして、アーキテクチャで、重要なコンポーネントを構築します。ライブラリでは、あなたが望む場合、 あなたは、コンテナそのものでさえ、置き換えることさえできます。カスタマイズする他の共通の領域は、作成することが含まれています。 あるいは、あなた独自のコンテナを使用して、あなた独自のロガーを呼び出す、モジュールを読み込むための、 モジュール発見戦略を選択するために、ブートストラッパーをカスタマイズし、そして、あなた独自の領域アダプタを作成します。

このトピックは、Prism Library内のいくつかの重要な拡張ポイントを説明します。 これらは、より高等なトピックである傾向があり、ほとんどの開発者が、Prism Libraryを使用して、実行することは、期待していません。 Prism Libraryの目標と設計決定を確実に理解することは、副作用の作成、あるいは、アーキテクチャを低下させない、 Prismの機能に拡張を確実に行うために、役立ちます。Prismのドキュメンテーションの主なトピックは、Prism Library (原文)を拡張する前に、 読むことを推奨します。この文書で説明される技術のほとんどは、アプリケーションの起動時に、 ブートストラップ・シーケンスの間に、Prism Libraryのデフォルトコンフィグレーションを置き換える、 あるいは、変更することに依存しています。それで、序文のPrism主要な概念(原文)の項目を読むことは、前提条件です。

以下は、このトピックで取り扱われる、Prism Libraryの重要な拡張ポイントです。:

  • アプリケーションのBootstrapper

    これは、Prism Libraryの重要な拡張ポイントを説明します。

  • モジュール方式

    モジュール・アプリケーションを構築するとき、これは拡張ポイントを説明します。

  • 領域管理

    この拡張は、どのように、領域が動作するか、それらが、どのように、格納されるか、そして、それらが、それらのViewと、どのように相互作用するか、説明します。

  • 領域ナビゲーション

    これは、あなたの論理ナビゲーション構造を、どのように変更するか説明します。

  • View Modelロケーター

    これは、View Modelロケーターを使用している時、規則を、どのように変更するかを説明します。

拡張性のためのガイドライン

Guidelines for Extensibility

あなたが、Prism Libraryを拡張するとき、これらのガイドラインを使用します。 あなたは、追加する、あるいは、サービスを置き換える、ソース・コードを変更する、あるいは、新しいアプリケーション機能を追加することで、ライブラリを拡張できます。

機能を公開する

Exposing Functionality

ライブラリは、その機能を公開するために、public APIを与える必要があります。 APIのインターフェイスは、内部実装から独立している必要があります。 開発者は、その既定の機能を効果的に使用するために、ライブラリの設計や実装を理解することを、求められていません。 可能な限り、APIは、固有の機能のための共通のシナリオを適用する必要があります。

ライブラリを拡張する

Extending Libraries

Prismライブラリは、開発者は、それらのニーズに合わせて、ライブラリを調整するために、使用することができる、拡張ポイントを提供します。 たとえば、Prism Libraryを使用するとき、あなたは、与えられたログの記録サービスを、あなた独自のログの記録サービスに置き換えることができます。

あなたは、そのソース・コードを変更することなく、ライブラリを拡張できます。 これを達成するために、あなたは、public基底クラスやインターフェイスのような、拡張ポイントを使用する必要があります。 開発者は、基底クラスを拡張することができる、あるいは、インターフェイスを実装することができ、 そして、ライブラリに、それらの拡張を追加します。拡張ポイントの設定を定義するとき、ユーザビリティ上で効果を考慮します。 拡張ポイントの多くは、使用するために、そして、設定することが難しい、複雑なライブラリを作成することができます。

一部の開発者は、拡張ポイントを使用して、ソース・コードを変更することを示す、コードをカスタマイズすることに、興味を持っている可能性があります。 この努力に対応するために、ライブラリ・デザインは、次のことを提供する必要があります。:

  • 実際的な場合はいつでも、オブジェクト指向デザインの原則に従う必要があります。
  • それは、適切なパターンを使用する必要があります。
  • それは、リソースを効率的に使用する必要があります。
  • それは、セキュリティの原則を厳守する必要があります。(たとえば、ユーザー入力を疑う、そして、最小特権の原則)

Prism Libraryを変更するための推奨事項

Recommendations for Modifying the Prism Library

ソース・コードを変更するとき、これらのベスト・プラクティスに従ってください。:

  • ライブラリが、トピックを読み込むことによって、どのように動作するかについて理解してください。 それは、そのデザインを説明します。あなたが、コードを大幅に変更する場合、 あるいは、あなたが、オリジナル・バージョンと一緒に、ライブラリのあなたがカスタマイズしたバージョンを使用したい場合、 ライブラリの名前空間を変更することについて、考えてみてください。
  • あなた独自のアセンブリを作成することについて、考えてみてください。 Prism Libraryバイナリを変更するか、置き換える前に、それは、はじめに、Prism Libraryに組み込まれた拡張ポイント使用します
  • 強い命名を使用する厳密な名前は、アセンブリ、バージョン、整合性の確認を一意に識別できます。 あなたは、アプリケーション・ブロックの変更されたバージョンに署名するために、あなた独自の鍵の対を作成する必要があります。 詳細については、MSDNの厳密な名前のアセンブリを参照してください。 他の方法として、あなたは、あなたのカスタム・バージョンに署名しないことを選択することができます。これは、弱い命名として参照されます。

Prism Libraryの拡張ポイント

Extensibility Points in the Prism Library

この項目は、機能分野によって、そして、ライブラリを拡張するための関連する情報の拡張ポイントの概要を述べます。

コンテナとBootstrapper

Container and Bootstrapper

Prism Libraryは、直接、依存関係注入コンテナとして、Unityアプリケーション・ブロック(Unity)と拡張管理フレームワーク(MEF)をサポートしています。; しかしながら、コンテナが、IServiceLocatorインターフェイスによって呼び出されるため、コンテナは、置き換えることができます。

各々のPrismアプリケーションは、ブートストラッパー・クラスによってPrism Libraryを設定します。ブートストラップ工程の各段階は、工程そのものと同様に、交換可能です。 ブートストラッパーは、デフォルトの実装をカスタム実装で、あるいは、追加のデータ型とサービスを登録する、交換をするために、重要な拡張ポイントを提供します。

ログの記録

Logging

いくつかのPrism Libraryコンポーネントは、情報、警告メッセージやエラーメッセージを記録します。 個々のログの記録アプローチの依存関係を回避するために、それは、ILoggerFacadeインターフェイスに、これらのメッセージを記録します。 一般的な拡張は、特定のアプリケーションのためのカスタム・ロガーを提供します。

モジュール

Modules

Prism Libraryは、モジュール・カタログを埋め込むさまざまな方法とロードモジュールを提供します。; しかしながら、あなたのシナリオは、ライブラリを与えない必要があるかもしれません。

モジュールの読み込みは、次の3つの段階が含まれています。それは、カスタマイズすることができます。:

  • モジュール発見。これは、モジュール・カタログを埋め込む工程です。 頻繁に、これは、直接、あるいは、ディレクトリを掃引することにより行われます。 しかし、あなたのアプリケーションは、データベースからのような、いくつかのその他の方法で行う必要があるかもしれません。 これらの場合では、あなたは、適切なソースからそれ自体を埋め込む、カスタム・カタログを作成することができます。
  • モジュールの検索と読み込み。これは、ローカルに、モジュール・バイナリを取得する工程です。 そして、現在のアプリケーション・ドメインに、モジュールを読み込みます。 ライブラリは、FileModuleTypeLoaderを提供しますが、あなた独自の探索戦略を実装することもできます。
  • モジュールの初期化。これは、モジュールを初期化する工程です。 ライブラリでは、これは、ModuleInitializerによって行われます。 しかし、それは、IModuleInitialzerを実装する、新しいオブジェクトを提供することで、置き換えることができます。

Region

Prismライブラリは、領域として、コントロールを可能にするために、既定のコントロール・アダプタを提供します。 領域の周りの拡張は、カスタム領域アダプタ、カスタム領域を与える、あるいは、領域マネージャーを置き換えることを必要とするかもしれません。 あなたが、それは、与えられた領域アダプタでは、動作しない、カスタムWPFコントロールやサードパーティ製のコントロールを持っている場合、 あなたは、カスタム領域アダプタを作成するといいかもしれません。 また、それは、コンテナに、新しいIRegionManagerを提供することによって、既定のRegionManagerを置き換えることができます。

領域ナビゲーション

Region Navigation

また、Prism Libraryの領域機能は、ナビゲーションをサポートしています。戻る/進むの更新履歴サポートが含まれています。 領域の中のViewは、INavigationAwareインターフェイスを通して、ナビゲーション内で、拡張、そして、関与することができます。 Silverlightナビゲーション機能に精通している開発者は、Frameクラスに類似した領域を見つけるでしょう。 領域ナビゲーションは、いくつかの拡張ポイントをサポートしています。 それは、ナビゲーション・サービスの置き換えに加えて、アプリケーションの論理的なナビゲーション構造を変更するために、それを可能にします。

RegionNavigationContentLoaderクラスは、NavigationContextに基づいた領域に、内容を読み込む能力を提供します。 移動される内容が、すでに領域内にある場合、RegionNavigationContentLoaderは、その内容を配置します。 そして、領域を追加するための新しい内容を作成する代わりに、それをアクティブとして作成します。 RegionNavigationContentLoader.GetCandidatesFromRegionメソッドは、 型で、それらと一致している領域Viewを検索します。 しかしながら、それは、Viewが、解決するために使用される型と一致しない型を持つことは、可能です。 例えば、あなたは、「親しみやすい」名前を使用して、依存関係注入コンテナで、Viewを登録することができました。 それは、あなたのView型の名前と一致しません。

C#


[Export("FriendlyName")]
public class MyViewType

Prismライブラリは、UnityRegionNavigationContentLoaderとMefRegionNavigationContentLoaderを発送します。 それは、可能な親しみやすい名前の登録をView型に基づいて見つけるのに、必要な特別な処理を提供する、 GetCandidatesFromRegion基底メソッドを上書きします。 あなたが、UnityRegionNavigationContentLoaderかMefRegionNavigationContentLoaderを使用していない場合、 続いて、依存関係注入コンテナに、あなたが使用する、RegionNavigationContentLoaderの部分クラスに操作が追加されていることを確認します。

コンテナとBootstrapper

Container and Bootstrapper

Prism Libraryには、Bootstrapper基底クラスが含まれています。UnityとMEFコンポーネントは、 それぞれ、UnityBootstrapperとMefBootstrapperとして、このクラスから派生します。 Bootstrapper基底クラスは、工程の正確な順序付けを、派生クラスに残す、抽象的なRunメソッドを定義します。 ほとんどすべてのメソッドは、カスタマイズ、そして、ブートストラップ工程を拡張するために、それぞれのメソッドを上書できる、仮想であるように、マークされます。

ほとんどの型のインスタンス化のために、ブートストラッパーは、依存関係注入コンテナを使用するでしょうしかしながら、 コンテナを使用することができない、ブートストラップ工程のいくつかの部分があります。:

  • ロガーを作成する

    通常、ロガーは、まず、(コンテナの前に)作成されます。 ブートストラッパーは、コンテナを作成することに関する情報を記録する必要があるため、 ログの記録の実装を変更することの詳細については、「ログの記録」の項目を参照してください。

  • カタログを作成して、設定する

    カタログ(たとえば、ModuleCatalogとAggregateCatalog)は、 コンテナ構築の間、使用されるため、コンテナの前に、作成されます。

  • シェルを作成する

    ブートストラップ・シーケンスを実行する前に、シェルがすでに存在するかもしれないため、 CreateShellメソッドは、実装するアプリケーション開発者のため、抽象として、残っています。 アプリケーション開発者は、コンテナが作成され、そして、初期化されたため、シェルをインスタンス化、 あるいは、配置するために、コンテナを使用することができます。

既定のPrism Library型を置き換える

Replacing Default Prism Library Types

あなたが、アプリケーションのために、Prism Library型の基盤となる実装を変更、 あるいは、拡張する必要があるとき、時間があるかもしれません。 Prism Libraryが、依存関係注入に依存するため、あなたは、ブートストラップ・シーケンスの間、型を置き換えることができます。 そして、あなたのアプリケーションとPrism Libraryは、新しい型を使用するでしょう。

Unityを使用して、既定のデータ型を置き換える

Replacing Default Types Using Unity

UnityBootstrapper.ConfigureContainerメソッドが、呼び出される前に、 どんな置換型でも、コンテナに登録しまし、型を置き換えるでしょう。その関連付けられたインターフェイスが、すでに登録されていない場合、 ConfigureContainerデフォルトの実装は、Prism Library型を追加するためだけに、RegisterTypeIfMissingメソッドを使用します。

Prism Library型をUnityに置き換えるために、 まず、あなたが、置き換えたい、インターフェイスやクラスから、あなたの新しい型を派生します。 次のコード例は、IEventAggregatorインターフェイスの置き換えを示します。

C#


// when using Unity
public class ReplacementEventAggregator : IEventAggregator 
{
    // ...
}

今、あなたは、ブートストラッパーで、ConfigureContainerメソッドを上書きする、インターフェイスと型を登録する、 基底クラスを呼び出す前に、置き換えた型を持っています。 次のコード例は、どのように、IEventAggregatorの置き換えを登録するかを示します。

C#


// when using Unity
protected override void ConfigureContainer()
{
    this.RegisterTypeIfMissing(typeof(IEventAggregator), typeof(ReplacementEventAggregator), true);
 
    base.ConfigureContainer();
}

MEFを使用して、既定の型を置き換える

Replacing Default Types Using MEF

MefBootstrapper.ConfigureContainerメソッドが、呼び出される前に、どんな置換型でも、コンテナに登録し、型を置き換えるでしょう。 その関連付けられたインターフェイスが、すでに登録されていない場合、ConfigureContainerの既定の実装は、Prism Library型を一つだけ追加します。

Prism Library型をMEFに置き換えるために、まず、あなたが望むインターフェイスから、適切なMEFエクスポート属性を、それに置き換えて、 適用するために、あなたの新しい型を派生します。次のコード例は、IEventAggregatorインターフェイスの置き換えを示します。

C#


// when using MEF
[Export(typeof(IEventAggregator))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class ReplacementEventAggregator : IEventAggregator
{
    // ...
}

今、あなたは、ブートストラッパーで、ConfigureAggregateCatalogメソッドを上書きし、 そして、AggregateCatalog型に含まれるカタログを追加する、置き換えた型を持っています。 次のコード例は、置換型を追加するために、TypeCatalogを、どのように、使用するかを示しています。 また、AssemblyCatalogは、使用することができます。

C#


// when using MEF
protected override void ConfigureAggregateCatalog()
{
    this.AggregateCatalog.Catalogs.Add(new TypeCatalog(typeof(ReplacementEventAggregator)));

    base.ConfigureAggregateCatalog();
}

MEFコンテナに、非MEF属性型を登録する

Registering Non-MEF Attributed Types with the MEF Container

あなたが、コードを所有し、そして、MEF上で、直接、依存関係を取得する場合、 あなたは、Export属性を型に追加するだけなので、MEFで型を登録することは、簡単です。 しかしながら、いくつかの状況では、あなたが、MEFアセンブリの上で、直接、依存関係を取得できないとき、 あなたは、MEFで、型を登録することを必要とするかもしれません。 この問題は、MEFサポートをPrismに追加している間に、設計目標の1つを確実とするため、 コアPrismライブラリが、コンテナ固有でなかったために、開発者が、直面しました。 これは、Microsoft.Practices.Prismアセンブリが、System.ComponentModel.Compositionを参照することができない、 そして、Export属性を使用することを示しています。 その代わりに、チームは、Microsoft.Practices.Prism.MefExtensionsアセンブリに、派生クラスを作成しました。 それは、チームが、公開することを望んだ型から派生し、そして、適切な型をエクスポートします。 MefRegionManagerクラスから、次のコード例は、RegionManagerから派生し、 そして、IRegionManagerとして、新しい型をエクスポートすることで、このアプローチの例を示しています。

C#


[Export(typeof(IRegionManager))]
public class MefRegionManager : RegionManager
{
}

最少のBootstrapperを作成する

Creating a Minimal Bootstrapper

一部のアプリケーションでは、Prism Libraryの機能の多くを使用していません。 場合によっては、アプリケーション開発者は、絶対最小のサービス水準を望むかもしれません。 -依存関係の注入とサービスの位置だけ、これを実行するには、 次に示すブートストラッパーと実装で、ConfigureContainerメソッドを上書きします。

C#


// when using UnityBootstrapper
// UnityBootstrapperを使用するとき、
protected override void ConfigureContainer()
{
    // Base class implementation deliberately not called
    // base.ConfigureContainer();
    // 基底クラスの実装は、故意に、base.ConfigureContainer()を呼び出しません。;
 
    this.Container.AddNewExtension<UnityBootstrapperExtension>();
    Container.RegisterInstance<ILoggerFacade>(Logger);
    this.Container.RegisterInstance(this.ModuleCatalog);            
    RegisterTypeIfMissing(typeof(IServiceLocator), typeof(UnityServiceLocatorAdapter), true);
}
 
protected override RegionAdapterMappings ConfigureRegionAdapterMappings()
{
    return null;
}
 
protected override IRegionBehaviorFactory ConfigureDefaultRegionBehaviors()
{
    return null;
}

備考

領域アダプタとマッピングのオーバーライドは、必要とされます。 Unityが、返すために、適切で、具体的な型を決定できないため、インターフェイスの実装が、要求されるとき、 これらは、それぞれのインターフェイスを返すために、具体的な型の関連付けを呼び出します。 必要とされる具体的な型が、要求されるとき、Unityは、型をインスタンス化することによって、直接、それらを解決することができます。

C#


// when using MEFBootstrapper
// MEFBootstrapperを使用するとき、
protected override void ConfigureContainer()
{
    // Base class implementation deliberately not called
    // base.ConfigureContainer();
    //基底クラスの実装は、故意に、base.ConfigureContainer()を呼び出しません。;
    
    this.Container.ComposeExportedValue<ILoggerFacade>(this.Logger);
    this.Container.ComposeExportedValue<IServiceLocator>(new MefServiceLocatorAdapter(this.Container));
    this.Container.ComposeExportedValue<AggregateCatalog>(this.AggregateCatalog);
}

依存関係注入コンテナを変更する

Changing Dependency Injection Containers

あなたが、あなたのアプリケーションで、UnityやMEF以外のコンテナ付きのPrismを使用する場合、あなたが、行う必要がある、いくつかのことがあります。 まず、あなたは、あなたのコンテナのためのサービス・ロケーター・アダプタを記述することを必要とします。 あなたは、どのように、行うことができるかの例として、MefServiceLocatorAdapterとUnityServiceLocatorAdapterを使用することができます。 また、あなたは、コンテナ固有のブートストラッパー・クラスを記述する必要があります。 次に、あなたは、新しいコンテナ固有のブートストラッパーを作成する必要があります。 例として、MefBootstrapperとUnityBootstrapperの利用して、Bootstrapperクラスから派生し、そして、必要なメソッドを実装します。

ログの記録

Logging

Prism Libraryは、ライブラリを通して、メッセージをログに記録するように設計されています。 この方法で、ログを記録するために、それは、固有のログの記録ライブラリに拘束されません。 Prism Libraryは、そのメッセージを記録するために、ログの記録外見、ILoggerFacade、を使用します。 このインターフェイスには、ログ・メッセージを記録する、Logという名前の一つのメソッドが含まれています。 既定では、UnityBootstrapperとMefBoostrapperは、指定されたロガーとして、TextLoggerを作成します。

カスタム・ロガーを作成して、統合するための、3つの段階があります。:

  • ILoggerFacadeインターフェイスを実装するクラスを作成します。
  • ログ・メソッドを実装します。
  • あなたのアプリケーション・ブートストラッパー・クラスでは、 あなたのログの記録クラスの新しいインスタンスを返すために、CreateLoggerメソッドを上書きします。

ILoggerFacadeインターフェイスのLogメソッドは、3つのパラメータを取得します。:

  • メッセージ Message

    これは、記録されるメッセージです。

  • 分類Category

    これは、記録されるイベントの分類です。有効なオプションは、Debug、Exception、InfoとWarnです。

  • 優先順位。Priority

    これは、記録されるイベントの優先順位です。有効なオプションは、None、High、MediumとLowです。

次のコード例は、文字列だけを取得する、いくつかの他のログの記録フレームワークをラップする、カスタム・ロガーを示します。

C#


// CustomeLogger
using Microsoft.Practices.Prism.Logging;
...

public class CustomLogger : ILoggerFacade
{
    public void Log(string message, Category category, Priority priority)
    {
        string messageToLog =        
            String.Format(System.Globalization.CultureInfo.InvariantCulture, 
                "{1}: {2}. Priority: {3}. Timestamp:{0:u}.", 
                DateTime.Now,                
                category.ToString().ToUpperInvariant(), 
                message, 
                priority.ToString());

        MyOtherLoggingFramework.Log(messageToLog);
    }
}

C#


// ApplicationBootstrapper
using Microsoft.Practices.Prism.Logging;
...

public class ApplicationBootstrapper : UnityBootstrapper
{
    ...
    protected override ILoggerFacade CreateLogger()
    {
        return new CustomLogger();
    }
}

モジュール

Modules

次の項目は、モジュール方式機能が、登録、アセンブリ発見、型検出とモジュール初期化の間、どのように、拡張されるかを説明します。

機能をModuleカタログに追加する

Adding Features to the Module Catalog

Prismライブラリは、両方のクラスとして、ModuleCatalogを提供します。 あなたは、AddModuleメソッドを通して、直接、埋め込むことができます。 あるいは、あなたは、Itemsプロパティを埋め込むために、addメソッドから、派生することができます。

Prism LibraryのModuleCatalogクラスは、IModuleインターフェイスを越えた追加機能の多くを提供します。 AddModuleメソッド、モジュール・グループの依存関係の検証と並べ替えの多くの異なるオーバーロードがあリます。 ModuleCatalogの機能を拡張する、いくつかの方法があります。:

ModuleCatalogから派生します。 あなたが、ModuleCatalogの挙動を変更する必要がある場合、新しいクラスを派生し、そして、仮想メソッドを上書きします。

IModuleCatalog上で、拡張メソッドを記述します。 あなたが、IModuleCatalogを使用するアプリケーションにおいて、 追加の機能を必要とする場合、インターフェイス上で、拡張メソッドを記述します。

ModuleCatalog上で、拡張メソッドを記述します。 あなたが、追加の機能を必要とする場合、 しかし、あなたが、ModuleCatalogを使用する場所だけで、具体的な型の上で、拡張メソッドを記述します。

カスタム・ソースからモジュールを発見する

Discovering Modules from a Custom Source

Prism Libraryは、アプリケーション設定から、 そして、XAMLファイルから、モジュール・カタログを埋め込むことをサポートしています。 あなたは、Webサービス、データベース、他の外部ファイルのような、 他のデータ・ソースからの読み込みをサポートするために、あなたのアプリケーション内で、Prismを拡張できます。

以下は、カタログを埋め込むための、いくつかの方法を説明します。

  • 静的CreateFromXamlメソッドを使用します。あなたのデータが、すでにModularityである場合、:
  • ModuleCatalog XAMLスキーマー、あるいは、それが、簡単に変換することができる場合、 あなたは、直接、ModuleCatalogを埋め込む、このメソッドを使用することができます。 ConfigurationModuleCatalog内の、IConfigurationStoreを置き換えます。
  • あなたが、WPFデスクトップ・アプリケーションを実行する場合、 あなたは、ConfigurationModuleCatalogのためのモジュール項目を返すために、 IConfigurationStoreを実装することができます。
  • ModuleCatalogから派生します。また、あなたは、ModuleCatalogから派生するために、 ConfigurationModuleCatalogの例に従うことができます。あなたのデータを取得します。 そして、その次に、カタログを埋め込むために、AddModuleメソッドを呼び出します。

以下のコード例は、ディスクから、カスタム設定モジュール・ファイルを、どのように、読み込むかを示しています。

C#


// Bootstrapper
protected override Microsoft.Practices.Prism.Modularity.IModuleCatalog CreateModuleCatalog()
{
    ConfigurationModuleCatalog catalog = new ConfigurationModuleCatalog();
    catalog.Store = new MyModuleCatalogStore();
    return catalog;
}

C#


// MyModuleCatalogStore
public class MyModuleCatalogStore : IConfigurationStore
    {
        public ModulesConfigurationSection RetrieveModuleConfigurationSection()
        {
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap()
            {
                ExeConfigFilename = "MyModuleCatalog.config"
            };
 
            Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            return configuration.GetSection("modules") as ModulesConfigurationSection;
        }
    }

カスタム・アセンブリ・ソースから、モジュールを取得して、読み込む

Retrieving and Loading Modules from a Custom Assembly Source

あなたのアプリケーションが、実装、あるいは、アセンブリ以外の配布の仕組みを持っている場合、 あなたは、型をダウンロードあるは呼び出すために、あなた独自のIModuleTypeLoaderを実装することができます。

Prism 4.1ライブラリのMefXapModuleTypeLoaderクラスは、XAPファイルをダウンロードする、アセンブリを配置する、 そして、それらとMEFカタログを登録するために、MEF DeploymentCatalogを使用する例です。 各々のIModuleTypeLoaderは、モジュールを取得するために使用する、適切な型のローダーを決定するためにModuleManagerを提供する、 CanLoadModuleTypeメソッドを実装しています。次のコード例は、MefXapModuleTypeLoaderの実装を示しています。

C#


// MefXapModuleTypeLoader.cs
public bool CanLoadModuleType(ModuleInfo moduleInfo)
{
    if (moduleInfo == null)
    { 
        throw new ArgumentNullException("moduleInfo"); 
    }
 
    if (!string.IsNullOrEmpty(moduleInfo.Ref))
    {
        Uri uriRef;
        return Uri.TryCreate(moduleInfo.Ref, UriKind.RelativeOrAbsolute, out uriRef);
    }
 
    return false;
}

あなたが、モジュール・データ型ローダーを持ったあと、 あなたは、それが、型ローダーのModuleManagerのコレクションであることを確実にする必要があります。 次のコード例は、Prism.MefExtensions.Silverlightプロジェクトからです。

C#


// MefModuleManager.Silverlight.cs
public override IEnumerable<IModuleTypeLoader> ModuleTypeLoaders
{
    get
    {
        if (this.mefTypeLoaders == null)
        {
            this.mefTypeLoaders = new List<IModuleTypeLoader>()
                                    { this.MefXapModuleTypeLoader };
        }
        return this.mefTypeLoaders;
    }
    set
    {
        this.mefTypeLoaders = value;
    }
}

モジュールの初期化を変更する方法

Changing How Modules Are Initialized

  • l ModuleCatalogに加えて、ModuleManagerは、多くの仮想関数を提供します。 それは、モジュールが、どのように、読み込まれて、初期化されるかを変更するために、上書きすることができます。 MefModuleManager内で、いくつかのメソッドを上書きするために、 MEFが必要なModuleManagerで、統合します。いくつかの方法が、ビヘイビアを変更するためにあります:
  • l ModuleManagerから派生します。あなたは、モジュールを読み込みと初期化シーケンスの基本的なビヘイビアを変更する必要がある場合、 新しいクラスから派生して、仮想メソッドを上書きします。
  • l あなたが、IModuleIntializerを置き換えて、モジュール型が、どのように、インスタンス化、 あるいは、初期化されるか変更する必要がある場合、IModuleIntializerを置き換えます。
  • l カスタムIModuleTypeLoaderを記述します。あなたが、アセンブリが、どのように、読み込まれるか、そして、アセンブリ内の、 モジュール型を発見するかを変更する必要がある場合、カスタムIModuleTypeLoaderを記述します。 詳細については、カスタム・アセンブリ・ソースから、モジュールを取得して、読み込む項目(原文)を参照してください。

Region

次のセクションでは、領域が、コントロールに添付されるとき、拡張されることができるPrism Libraryの領域管理が、 どのように、機能するか、どのように、領域が動作するか、そして、領域が、そのViewをどのように発見するか、を説明します。

領域アダプタ

Region Adapters

領域アダプタは、ホスト・コントロールと相互作用する領域で、項目を、どのように、配置するかを制御します。 次のセクションでは、カスタム領域アダプタとアダプタの登録を制御することを作成することで、このビヘイビアを、どのように、拡張するかを説明します。

ユーザー定義した領域アダプタを作成する

Creating a Custom Region Adapter

領域として、UIコントロールを公開するために、領域アダプタは使用されます。 領域アダプタは、領域を作成するための、そして、それをコントロールに関連付けるための、役割を果たします。 これを行うことによって、開発者は、IRegionインターフェイスによって、一貫した方法で、UIコントロールの内容を管理することができます。 それぞれの領域アダプタは、UIコントロールのそれぞれの型に合わせます。Prismライブラリは、すぐに使える3つの領域アダプタを提供します。:

  • ContentControlRegionAdapter

    このアダプタは、System.Windows.Controls.ContentControl型と派生クラスのコントロールに適応させます。

  • SelectorRegionAdapter

    このアダプタは、System.Windows.Controls.TabControlコントロールのような、 System.Windows.Controls.Primitives.Selectorクラスから派生したコントロールに適応させます。

  • ItemsControlRegionAdapter

    このアダプタは、System.Windows.Controls.ItemsControl型と派生クラスのコントロールに適応させます。

前述の領域アダプタのどれでもが、開発者の必要に適切ではない、いくつかのシナリオが、あります。 それらの場合において、カスタム領域アダプタは、すぐに使えるPrism Libraryで、 サポートされない、コントロールに適応させために作成することができます。

領域アダプタは、Microsoft.Practices.Prism.Regions.IRegionAdapterインターフェイスを実装します。 このインターフェイスは、適応するために、オブジェクトを取得する、Initializeという名前の、一つのメソッドを定義します。 そして、適応するコントロールで関連付けられる、新しい領域を返します。インタフェース定義は、次のコードで示されます。

C#


public interface IRegionAdapter
{
    IRegion Initialize(object regionTarget, string regionName);
}

領域アダプタを作成するために、あなたは、RegionAdapterBaseからクラスを派生して、 CreateRegionを実装して、メソッドに合わせます。必要に応じて、領域ビヘイビアをカスタマイズするために、 特別なロジックを添付するために、AttachBehaviorsメソッドを上書きします。 あなたが、領域を格納するコントロールと相互作用したい場合、 また、あなたは、IHostAwareRegionBehaviorを実装する必要があります。

CreateRegionメソッドは、RegionAdapterBaseクラスで定義される抽象メソッドです。 それは、適応するコントロールに関連付けるために、(オブジェクトは、IRegionインターフェイスを実装します)領域インスタンスを返します。 Prism Libraryは、すぐに使える、次の領域の実装を提供します。:

  • Regions

    この領域は、複数のアクティブViewを提供します。 これは、Selectorクラスから派生したコントロールのために、使用される領域です。

  • SingleActiveRegion

    この領域は、一度に、最大1つのアクティブ・ビューを提供します。 これは、ContentControlコントロールのために、使用される領域です。

  • AllActiveRegion

    この領域は、その中の、すべてのViewをアクティブに保ちます。 Viewの無効化が許可されていません。これは、ItemsControlコントロールのために、使用される領域です。

また、Adaptメソッドは、RegionAdapterBaseクラスで定義される抽象メソッドです。 それは、以前に作成された領域に適応します。Adaptメソッドは、2つのパラメータを取ります。: コントロールが適応する領域は、関連付けられ、コントロールに適応します。 次のコード例は、ContentControlRegionAdapterを示します。

C#


public class ContentControlRegionAdapter : RegionAdapterBase<ContentControl>
{
    public ContentControlRegionAdapter(IRegionBehaviorFactory regionBehaviorFactory)
        : base(regionBehaviorFactory)
    {
    }

    protected override void Adapt(IRegion region, ContentControl regionTarget)
    {
        if (regionTarget == null) throw new ArgumentNullException("regionTarget");
        bool contentIsSet = regionTarget.Content != null;
        contentIsSet = contentIsSet || (BindingOperations.GetBinding(regionTarget, ContentControl.ContentProperty) != null);

        if (contentIsSet)
        {
            throw new InvalidOperationException(Resources.ContentControlHasContentException);
        }
 
        region.ActiveViews.CollectionChanged += delegate
        {
            regionTarget.Content = region.ActiveViews.FirstOrDefault();
        };
 
        region.Views.CollectionChanged +=
            (sender, e) =>
            {
                if (e.Action == NotifyCollectionChangedAction.Add && region.ActiveViews.Count() == 0)
                {
                    region.Activate(e.NewItems[0]);
                }
            };
    }

    protected override IRegion CreateRegion()
    {
        return new SingleActiveRegion();
    }

}

備考

領域アダプタは、シングルトン・サービスとして登録されます。そして、アプリケーションの寿命を通して生きた状態で保たれます。 それで、あなたが、おそらく、UIコントロールや領域インスタンスのような、短い生きているオブジェクトの参照を維持していないことを確認してください。

正しい領域アダプタを関連付ける、領域マネージャー・サービスで、XAMLが定義する領域のための、領域アダプタ・マッピングが、使用されています。 次の項目は、領域アダプタ・マッピングの登録を、どのように、カスタマイズするかを説明します。

領域アダプタ・マッピングをカスタマイズする

Customizing the Region Adapter Mappings

起動するプロセスの1つの段階は、既定の領域のアダプタ・マッピングを登録することになっています。 これらのマッピングが、正しいアダプタを関連付けるために、XAMLが定義する領域のための領域マネージャーで、使用されています。 既定では、ItemsControlRegionAdapter、ContentControlRegionAdapterとSelectorRegionAdapterが、登録されます。 これらのアダプタの詳細については、User Interfaceを構成する(原文)を参照してください。

C#


// Bootstrapper.cs
protected virtual RegionAdapterMappings ConfigureRegionAdapterMappings()
{
    RegionAdapterMappings regionAdapterMappings = ServiceLocator.Current.GetInstance<RegionAdapterMappings>();
    if (regionAdapterMappings != null)
    {
        regionAdapterMappings.RegisterMapping(typeof(Selector), ServiceLocator.Current.GetInstance<SelectorRegionAdapter>());
        regionAdapterMappings.RegisterMapping(typeof(ItemsControl), ServiceLocator.Current.GetInstance<ItemsControlRegionAdapter>());
        regionAdapterMappings.RegisterMapping(typeof(ContentControl), ServiceLocator.Current.GetInstance<ContentControlRegionAdapter>());
    }
 
    return regionAdapterMappings;
}

領域ビヘイビア

Region Behaviors

領域ビヘイビアは、領域のための機能のほとんどを与えるPrism Libraryで使用されています。ブートストラップ工程の間、ブートストラッパーは、領域ビヘイビアを登録します。 それは、既定で、各々の領域に添付されます。さらに、アダプタは、領域が、特定のコントロール型だけで、関連付けられるとき、ビヘイビアを追加するかもしれません。

すべての領域のための領域ビヘイビアを追加する

Adding a Region Behavior for All Regions

あなたが、ビヘイビアを作成するか、既存のものを拡張したあと、あなたは、それを登録することができます。 それで、それは、すべての新しい領域に追加されます。 あなたは、ブートストラッパー内の、ConfigureDefaultRegionBehaviorsを上書きすることで、行うことができます。 次のコード例は、すべての領域のカスタム・ビヘイビアを、どのように、追加するかを示します。

C#


protected override IRegionBehaviorFactory ConfigureDefaultRegionBehaviors()
{
    IRegionBehaviorFactory factory = base.ConfigureDefaultRegionBehaviors();
    factory.AddIfMissing("MyBehavior", typeof(MyCustomBehavior));
}

既存の領域ビヘイビアを置き換える

Replacing an Existing Region Behavior

あなたが、既定のビヘイビアを、異なるビヘイビアに置き換えたい場合、 あなたは、あなたのアプリケーション固有のブートストラッパーで、ConfigureDefaultRegionBehaviorsメソッドを上書きすることで、それを追加することができます。 そして、あなたのビヘイビアを、既定のビヘイビアとして、同じキー値と一緒に登録します。 Prism Libraryは、そのキーと一緒にビヘイビアが、すでに追加されていない場合のみ、既定の領域ビヘイビアを追加します。

時折、あなたは、個々のView上に、領域ビヘイビアを、領域に追加、あるいは、置き換えたいかもしれません。 それらの領域が、ほとんどの領域のように、XAML内で定義される場合、領域は、あなたのカスタム・ビヘイビアを添付するために、最初に、利用できないかもしれません。 あなたは、領域の有効性を監視し、そして、あなたのビヘイビアを添付する必要があります。 領域が、利用できるようになるとき、次のコード例は、領域が、利用できるようになるとき、 AutoPopulateBehaviorを、あなたのカスタム・バージョンに、どのように、置き換えるかを示します。

C#


public class MyView : UserControl
{
    public MyView()
    {
        InitializeComponent();

        ObservableObject<IRegion> observableRegion = RegionManager.GetObservableRegion(this.MyRegionHostControl);

        observableRegion.PropertyChanged += (sender, args) => 
        {
            IRegion region = ((ObservableObject<IRegion>)sender).Value;
            region.Behaviors.Add(AutoPopulateBehavior.BehaviorKey, 
                new CustomAutoPopulateBehavior());
        };
    }
}

領域ビヘイビアを削除する

Removing a Region Behavior

それが追加されたあと、既存のビヘイビアを削除する方法がありませんが、 あなたは、あなたのアプリケーション固有のブートストラッパーで、ConfigureDefaultRegionBehaviorsメソッドを上書きすることによって、 ビヘイビアが追加されるのを妨げることができます。

Viewが、どのように、発見されるかを変更する

Changing How Views Are Discovered

あなたは、Viewが、どのように、登録、あるいは、作成されるかを制御したいかもしれません。 View発見を使用するとき、以下は、View発見を拡張するためのアプローチです。:

  • カスタムRegionViewRegistry

    あなたが、型の登録についての追加のコントロールを持ちたい(たとえば、 レジストリのスコーピング)あるいは、あなたの型の作成を制御したい場合、あなたは、このクラスから派生する必要があります。

  • カスタムAutoPopulateBehavior

    あなたが、その登録されたViewで、どこの領域で発見するかを変更したい場合、 (あなたが、RegionViewRegistryを使用したくない場合)あるいは、あなたは、Viewが、実際に、領域に追加されるが変更したい場合、 (たとえば、あなたが、フィルタリングするための能力を提供したい場合)、 あなたは、すべての領域のための、一つの領域、あるいは、既定に変更するために、カスタムAutoPopulateBehaviorを作成することができます。

領域ナビゲーション

Region Navigation

次のセクションでは、Prism Libraryの領域ナビゲーション機能を、どのように、拡張するかを説明します。

あなたの論理的ナビゲーション構造を変更する

Changing Your Logical Navigation Structure

Prism Libraryの領域ナビゲーション機能は、ナビゲーション統一リソース識別子 (URI)として、各々のviewの型名を使用します。 あなたのアプリケーションは、View型名から独立した、URIナビゲーション・スキームを公開したいかもしれません。

WPFアプリケーションは、同じ結果を得るために、IRegionNavigationContentLoader実装を置き換えることができます。 また、多標的アプリケーションは、この方法を使用する、アプリケーションのためのURI構造が定義される一つの場所を維持することを望むかもしれません。

論理ナビゲーション構造を変更するために、新しいクラスを派生します。 RegionNavigationContentLoaderとオーバーライドしたGetContractFromNavigationContextメソッドから、 メソッド内で、読み込むView型名を、入力契約名に変換します。それは、基底クラスを呼び出すために、推奨されます。 なぜなら、それは、URIを、検査する契約文字列に、都合良く、解析します。 次のコード例は、カスタム領域のコンテンツ・ローダーを示します。 それは、「Home」をHomeビューに、そして、「About」をAboutビューにマッピングします。

備考

この例では、エクスポート属性は、MEFコンテナで利用できるように、クラスの一番上に、適用して、MEFを使用します。

C#


[Export(typeof(IRegionNavigationContentLoader))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class CustomRegionNavigationContentLoader : RegionNavigationContentLoader
{
    [ImportingConstructor]
    public CustomRegionNavigationContentLoader(IServiceLocator serviceLocator)
        : base(serviceLocator)
    {
    }
 
    protected override string GetContractFromNavigationContext(NavigationContext navigationContext)
    {

        string contract = base.GetContractFromNavigationContext(navigationContext);
 
        if (contract.Equals("Home", StringComparison.OrdinalIgnoreCase))
        {
            return typeof(HomeView).Name;
        }
 
        if (contract.Equals("About", StringComparison.OrdinalIgnoreCase))
        {
            return typeof(AboutView).Name;
        }
 
        return contract;
    }
}

あなたが、カスタム・ナビゲーション・コンテンツ・ローダーを持ったあと、 それを、コンテナ内のIRegionNavigationContentLoaderの実装として、置き換えます。 コンテナ内で、置き換える型の詳細については、このトピックの初めの、コンテナとBootstrapperの項目を参照してください。

高等なナビゲーションの置き換え

Advanced Navigation Replacements

次のセクションでは、Prism Libraryで、提供される領域ナビゲーション基盤構造の主要な部分を置き換えることを説明します。 ほとんどの開発者は、カスタマイズのこのレベルを必要とするシナリオを持っていません。

RegionNavigationContentLoader

RegionNavigationContentLoader型は、IRegionNavigationContentLoaderインターフェイスを実装しています。 あなたは、RegionNavigationContentLoaderから派生する、メソッドを上書きするかもしれません。 あるいは、完全にインターフェイスの実装を置き換えます。

LoadContentメソッドに加えて、RegionNavigationContentLoader型は、上書きするために、2つの他の可能なメソッドを持っています。 しかし、それらは、珍しい、ナビゲーション・シナリオを、一つだけ必要する必要があります。:

  • GetCandidatesFromRegion

    ナビゲーションの要求を処理するための候補の、このメソッドは、領域で、Viewを決定するフィルタを使用します。 特別なフィルタリングを行う、あるいは、候補ビューの並べ替えをする必要があるアプリケーションは、このメソッドを上書きする必要があります。

  • CreateNewRegionItem

    このメソッドは、ナビゲーションの要求を取り扱うことができる候補が、見つからない場合、Viewを作成するために呼び出されます。 IServiceLocatorを使用する既定の実装は、Viewのインスタンスを作成します。 アプリケーションは、コンテナの外側に、このメソッドを上書きするためのViewのインスタンスやシングルトンを返すために、特別なロジックを必要とします。

IRegionNavigationJournal/IRegionNavigationJournalEntry

領域ナビゲーション・サービスには、履歴が含まれています。それはナビゲーション履歴を記録して、「戻る」と「進む」ナビゲーションを与えます。 既定の実装は、標準的なスタック実装です。アプリケーションは、より高等な履歴と履歴機能を実装することを望みます。 (Internet ExplorerのBackボタンのドロップダウン・メニューのような)ビヘイビアを変更するために、RegionNavigationJournalを置き換える必要があるかもしれません。 そして、追加のデータを与えるために、Title領域とIcon領域のような、各々のエントリで、RegionNavigationJournalEntryを置き換える必要があるかもしれません。

IRegionNavigationService

領域ナビゲーション・サービスは、1つのViewから、もう一つへ、ナビゲーションを調整する中心となる機能を提供します。 アプリケーションは、他のナビゲーション・システムに委ねることを望みます。 あるいは、Prism Library内で、置き換えることを望む、 大量のナビゲーション・システムは、egionNavigationServiceを置き換える必要があります。

View Modelロケーター

View Model Locator

ViewModelロケーターは、その標準的な規則を使用して、ViewとView Modelを接続するために、MVVMの基本的なQuickStartで使用されます。 この項目は、Viewの命名と配置、命名、関連付け、関連するViewModelとViewの配置の規則を、どのように、変更するかを説明します。

ViewModelロケーターを使用するか、あるいは、MEFを使用して、 あなたのViewとViewModelを互いに接続するか、決定するための説明については、MVVMパターンを実装するを参照してください。 バックグラウンドとして、株トレーダーのリファレンス実装は、ViewとView Modelを接続するMEFを使用します。

View Model Locator規則を変更する

Changing the View Model Locator Conventions

ViewModelLocationProviderは、SetDefaultViewTypeToViewModelTypeResolverと呼び出される静的メソッドを提供します。 それは、ViewModelに、Viewを関連付けるための、あなた独自の規則を提供するために、使用できます。

C#


ViewModelLocationProvider.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
        {
            ...
            return viewModelType;
        });

既定では、View名前空間に配置される場合、Viewは、ViewModelに名前空間を更新する、 そして、Viewの名前に「ViewModel」接尾辞を添付するでしょう。 Prismは、同じアセンブリで、このViewModelを探すでしょう。

コンテナを使用するために、ViewModelLocationProviderを設定する

Configuring the ViewModelLocationProvider to Use a Container

次の例は、コンテナを使用して、ViewModelを構築するために、ViewModelLocationProviderを、どのように、設定するかを示します。

あなたのアプリケーションを起動する時、VieModel型を解決するためのあなたのコンテナを使用するために、 SetDefaultViewModelFactoryメソッドを使用します。 以下は、MicrosoftのUnity依存関係注入コンテナを使用する例です。

C#


IUnityContainer _container = new UnityContainer()
...
ViewModelLocationProvider.SetDefaultViewModelFactory((t)=> _container.Resolve(t));        

あなたが、ViewModel内に、既定のコンストラクタを持っている、 そして、注入される依存関係がない場合、ViewModelを作成するための既定の戦略は、 有効なアプローチのActivator.CreateInstanceメソッドを使用することです。

このエントリーをはてなブックマークに追加

Home PC C# Illustration

Copyright (C) 2011 Horio Kazuhiko(kukekko) All Rights Reserved.
kukekko@gmail.com
ご連絡の際は、お問い合わせページのURLの明記をお願いします。
「掲載内容は私自身の見解であり、所属する組織を代表するものではありません。」