かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

Prism 7.x で DI コンテナ固有の機能を使いたい

Prism 7 系で色々仕様変更がありましたが、その中でも大きな変更のうちの 1 つが DI コンテナにクラスを登録する処理の変更です。今までは各 DI コンテナのクラスを直接触っていましたが IContainerRegistry インターフェースというインターフェースが Prism から提供されて、それに対してクラスを登録するという形になりました。

IContainerRegistry は、各々の DI コンテナごとに実装があって、その先で DI コンテナの個別の API を呼び出しています。利用者からしたら DI コンテナに何を使っていたとしても Prism の提供する箱庭の中にいる限りは同じコードでよくなるというようになっています。

IContaienrRegistry インターフェースには以下のようなメソッドが定義されています。

  • RegisterInstance
  • RegisterSingleton
  • Register
  • IsRegistered

登録系機能オンリーって感じですね。

そのほかに Prism.Wpf や Prism.Forms で画面遷移用にページを追加するための RegisterForNavigation などの拡張メソッドが定義されています。

DI コンテナ固有の API を呼びたい

ということで、Prism を基本的に使う上で必要な処理が、どの DI コンテナを使っていたとしても同じように書けるように改善されています。 ところで、DI コンテナ固有のパワフルな機能を呼びたいとしたらどうするの?という疑問が出てきますが、これも一応逃げ道が用意されています。

IContainerRegistry インターフェースには、各 DI コンテナ固有の実装が入っているパッケージ(Prism.Unity.Forms や Prism.DryIoc.Forms や Prism.Unity.Wpf など) に GetContainer という拡張メソッドが定義されています。

これを使うと各 DI コンテナの生のインスタンスが取れるので、これを使うことで DI コンテナ固有の機能 (AOP や Resolve 時の引数の解決に独自処理を入れたりなど) を使うことができるようになっています。

ということで、これを使うと App クラスの RegisterTypes あたりでこんな風に書けるようになります。

protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
    // コンテナのインスタンスを取得する
    IUnityContainer container = containerRegistry.GetContainer(); // using Prism.Unity; をすると使えるようになる
    // コンテナ固有の機能にアクセス可能(この例では Unity の機能でコンストラクタに固定値を渡すようにしてる
    container.RegisterType<Sample>(new InjectionConstructor(10));
}

まとめ

Prism の用意してくれた IContainerRegistry という箱庭でおさまる場合はいいですけど、そうじゃない場合は今回紹介した GetContainer というメソッドを使ってお使いの DI コンテナ固有の機能を使って、よりパワフルな機能を使って便利に開発するのもいいかなって思います。

それでは、良い Prism Life を。