Prism.DryIocの使い方

# Prism.DryIocとは
Prism + DryIocを使用するためのオープンソースライブラリです。

# 準備
## Prism.DryIocのインストール
NuGetを利用して [Prism.DryIoc](https://www.nuget.org/packages/Prism.DryIoc/) をインストールできます。  

# PrismApplication
Prism.DryIocは最新バージョンのPrism Ver.7.1まで上げることができます (2019/6/27現在)。
Prism Ver.7.1では、Bootstrapperの代わりにPrismApplicationをAppに継承する形で使用します。
Prism.DryIoc.DryIocBootstrapperには、Obsolete属性が追加され継承したクラスの実装は非推奨となりました。

App.xamlではPrismApplicationを継承し、prismの名前空間を宣言します。
  
```xml
<prism:PrismApplication x:Class="DryIocMefAttributedModel.App"
             xmlns:prism="http://prismlibrary.com/">
```

App.xaml.csでは、PrismApplicationを継承します。

```cs
    public partial class App : PrismApplication
    {
        protected override Window CreateShell()
        {
            return ServiceLocator.Current.GetInstance<Views.MainWindow>();
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            // 型・インスタンスの登録
        }

        protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
        {
            // モジュールカタログの構成
        }
    }
```

## メイン画面の作成
App.CreateShellメソッドをoverrideし、App.CreateShellメソッド内でメイン画面を作成します。    

### ViewModelLocator
ViewとViewModelのインスタンスの依存関係を構築する仕組みを提供します。
Viewクラスの画面にViewModelLocatorを使用することを宣言します。  

```xml
<Window x:Class="PrismDryIocSample.Main.Views.MainWindow"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="MainWindow" Height="350" Width="525">
```
これによって、紐づけられるViewModelは以下のルールで設定されます。
Viewのフルネームが`PrismDryIocSample.Main.Views.MainWindow`のとき、`PrismDryIocSample.Main.ViewModels.MainWindowViewModel`となります。  

ViewModelがデフォルトコンストラクタのみ実装されている場合、DryIocは自動でコンテナに登録されるためViewModelの登録が不要です。  

## コンテナへ型・インスタンスを登録
DryIocでは、デフォルトコンストラクタのみ実装されているクラスは自動でコンテナに登録されます。
しかし、引数付きのコンストラクタをもつクラスやオプションを設定したい場合、登録しなければなりません。
RegisterTypesメソッドにて、DIコンテナを抽象化した`IContainerRegistry`を使用して型・インスタンスの登録します。 
ただし、引数付きのコンストラクタをもつクラスやオプションを設定したい場合、`IContainerRegistry`からDryIocコンテナを取得して登録します。  

```cs
        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            // オプションの設定などDryIocコンテナ独自の機能を使いたい場合
            var container = containerRegistry.GetContainer();
            container.Register<Items.Text>(/*オプション設定*/);

            // シングルトンクラスとして登録したい時
            containerRegistry.RegisterSingleton<Items.SingletonClass>();

            // 同じIFとして登録したい時
            // Items.Picture, Items.RichTextクラスはItems.IItemインターフェイスを継承している
            container.Register<Items.IItem, Items.Picture>(ifAlreadyRegistered: IfAlreadyRegistered.AppendNotKeyed);
            container.Register<Items.IItem, Items.RichText>(ifAlreadyRegistered: IfAlreadyRegistered.AppendNotKeyed);

            // 同じインスタンスでkeyを登録したいとき
            container.Register<Items.Text>(serviceKey: "1");
            container.Register<Items.Text>(serviceKey: "2");

            // containerRegistryからRegisterを実行するとDryIocコンテナ独自の機能は使えないため
            // デフォルトコンストラクタのみ実装されているクラスのみしか使用することができない
            // Items.Textクラスのコンストラクタはデフォルトコンストラクタのみ
            containerRegistry.Register<Items.Text>();
        }
```

カタログにモジュールを追加するには、ConfigureModuleCatalogメソッドにて`IModuleCatalog`にモジュールを追加します。  

```cs
        protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
        {
            moduleCatalog.AddModule<Modules.ModuleA>();
        }
```

## コンテナから型・インスタンスを取得
IModuleを継承したクラスのOnInitializedメソッドにて、DIコンテナを抽象化した`IContainerProvider`を使用して型・インスタンスの取得を行います。
  
```cs
        public void OnInitialized(IContainerProvider containerProvider)
        {
            var text = containerProvider.Resolve<Items.Text>();

            // ServiceLocatorから取得も可能
            var text2 = ServiceLocator.Current.GetInstance<Items.SampleClass>();
        }
```


# 参考文献
https://bitbucket.org/dadhi/dryioc/wiki/Home