ホーム > コンピュータ > C# > WPF in C# > Prism

ベクトルドロー・レベルゼロ+

Prism Library 5.0 for WPFを使用して、アプリケーションを初期化する 03[C# WPF Prism]

概要

MVVMパターン調べていて、Prismというツールキットを見つけました。MVVMパターンを使用するためのもっとも人気のあるツールキットのようです。

原文

Initializing Applications Using the Prism Library 5.0 for WPF」(外部サイト)の和訳です。

訳文

Initializing Applications Using the Prism Library 5.0 for WPF(外部サイト)

パターンと実践 ディベロパー・センター

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

中心となる筋書き

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ライブラリで、格納されていません。 それで、モジュール・クラスインスタンスは、初期化が完了していたあと、ガーベージとして集められます。

Copyright (C) 2011-2016 kukekko All Rights Reserved.
kukekko@gmail.com
ご連絡の際はアドレスの@は半角にしてください。 また、お問い合わせページのURLの明記をお願いします。
「掲載内容は私自身の見解であり、所属する組織を代表するものではありません 」。
inserted by FC2 system