WPF と Prism.Unity で DI する


WPF アプリ開発で使われる MVVM フレームワークに Prism がありますが、 Prism は DI フレームワーク提供しています。
今回は Prism が提供する DI フレームワークの一つである Unity を使った DI のやり方を紹介していきます。

NuGet パッケージの取得

Prism.Unity を取得します。

コンテナへの登録

// DI コンテナの生成
IUnityContainer container = new UnityContainer();

// インターフェイスとクラスを紐づけて登録
container.RegisterType<IAnimal, Dog>();

// インスタンスを登録
container.RegisterInstance<IAnimal>(new Dog());

// シングルトンとして登録
container.RegisterSingleton<IAnimal, Dog>();

IUnityContainer クラスの Register...メソッドを使ってクラスを登録します。
RegisterType メソッドは常に登録したクラスのインスタンスを新しく生成してインジェクションしてくれます。
RegisterInstance メソッドは登録したインスタンスをインジェクションしてくれます。
RegisterSingleton メソッドは登録したクラスのインスタンスを一度だけ生成して以降は同じインスタンスをインジェクションしてくれます。

コンテナからの取得

var animal = container.Resolve<IAnimal>();
var viewModel = container.Resolve<MainViewModel>();

DI ではありませんが、登録したクラスをコンテナから直接取り出すこともできます。
インターフェースではなくクラスであればコンテナが自動で登録してくれているので、登録することなく取り出すことができます。

インジェクション

コンストラクタインジェクション

// コンストラクタ
public MainViewModel(IAnimal dog) {
}

コンストラクタの引数に DI してほしいクラスを宣言しておけば自動的にインジェクションしてくれます。

プロパティインジェクション

[Dependency]
public Person { get; set;}

プロパティに DI するためには Dependency アトリビュートを対象プロパティにつけます。
この際、get と set の両方を用意してやること、自動実装プロパティにしておくことが必要です。

使ってみる

App.xaml.cs
public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        IUnityContainer container = new UnityContainer();
        container.RegisterType<IAnimal, Dog>();
        container.RegisterType<IPerson, John>();
        var vm = container.Resolve<MainViewModel>();
        }
    }
MainViewModel
public class MainViewModel 
{
    [Dependency]
    public IPerson Person {get; set;}

    public MainWindow(IAnimal animal) {}
}

これで Person と animal インスタンスをインジェクションすることができます。
DI を受ける MainWindow クラスもコンテナに生成してもらう必要があります。