Prism関連
https://qiita.com/tera1707/items/4fda73d86eded283ec4f#prism%E9%96%A2%E9%80%A3wpfxaml
試した環境
モノ | バージョン |
---|---|
VisualStudio | 2017 |
Prism.Unity | 6.3.0 |
やりたいこと
今のところDI(DependencyInjection)を使ったことがない。
DIを使えば、単体テストが楽になる
、複数名で開発するときに分担しやすくなる
とか聞くが、具体的に何がどう楽になるのかがイメージがわかないので、実際にコードを書いてみて、なにが楽になるのか実感したい。
試した環境
モノ | バージョン |
---|---|
VisualStudio | 2017 |
Prism.Unity | 6.3.0 |
サンプルを元に考える
こちらをベースにさせていただいています。
using Microsoft.Practices.Unity;
using System;
namespace ConsoleApp10
{
class Program
{
static void Main(string[] args)
{
// DI コンテナを生成
UnityContainer container = new UnityContainer();
Console.WriteLine("[Main] 名前を指定してインスタンスを登録する。");
// 名前を指定してインスタンスを登録(RegisterInstance()) // ここでDogやCatのコンストラクタが呼ばれる(newしたものを登録してるから)
container.RegisterInstance<IAnimal>(new Dog());
container.RegisterInstance<IAnimal>(new Dog(3));
container.RegisterInstance<IAnimal>("Dog9", new Dog(9));
container.RegisterInstance<IAnimal>("Dog12", new Dog(12));
container.RegisterInstance<IAnimal>(new Cat());
// 依存性を注入する
Console.WriteLine("[Main] 依存性を注入する。");
var person = container.BuildUp<Person>(new Person());
// ペットを呼ぶ
Console.WriteLine("[Main] ペットを呼ぶ。");
person.CallPet();
Console.ReadLine();
}
}
// 動物インターフェース
public interface IAnimal
{
void Cry();// 鳴き声を出力する
}
// ネコ(IAnimalインターフェースの実装)
public class Cat : IAnimal
{
public Cat() => Console.WriteLine(" 猫 コンストラクタ");
public void Cry() => Console.WriteLine("ニャ~");
}
// イヌ(IAnimalインターフェースの実装)
public class Dog : IAnimal
{
private int Crynum = 0;// 鳴く回数
public void Cry()
{
for (int i = 0; i < Crynum; i++)
Console.WriteLine("バウ!");
}
public Dog()
{
Crynum = 0;
Console.WriteLine(" 犬 コンストラクタ(引数なし)");
}
public Dog(int cryNum)
{
Crynum = cryNum;
Console.WriteLine(" 犬 コンストラクタ(引数あり)");
}
}
// 依存性を注入されるクラス
public class Person
{
// 名前を指定すると、RegisterInstanceで名前を指定したものを使用する
//[Dependency("Dog12")]
// 名前を指定しないと、RegisterInstanceで名前を指定しておらず、一番後に登録されたものを使用する(あと勝ちで使われるっぽい)
[Dependency]
public IAnimal Pet { get; set; }
// ペットを呼ぶ
public void CallPet() => Pet.Cry();
}
}
コードの流れ
- 依存性の登録~注入までは、下記のような流れで行う。
-
UnityContainer container = new UnityContainer();
でDIコンテナを生成する -
container.RegisterInstance<インターフェース>(new インターフェースを実装したクラス);
でインスタンスをコンテナに登録する -
container.BuildUp<注入先クラス>(new 注入先クラス());
で、登録したコンテナを使って注入先クラスをnewすると同時に依存性(注入先で使うクラス達)を注入する - 注入先クラスで、注入されたクラス(のインスタンス)を使う
-
動作メモ
インスタンス化のタイミングについて
RegisterInstance
の引数には、外部でインスタンス化した、登録したいオブジェクトのインスタンスを指定する。そのため、RegisterInstance
が呼ばれたときには、すでに登録したいオブジェクトのインスタンス生成は完了している(= コンストラクタはすでに実行済み)。
注入される側の[Dependency]属性について
注入先クラスで注入されたものを使うときに、[Dependency("Dog9")]
のように名前を指定すると、RegisterInstanceで名前を指定して登録されたもののうち、名前が一致するものを使用する。
[Dependency("Dog9")]
public IAnimal Pet { get; set; }
注入先クラスで注入されたものを使うときに、[Dependency]
のように名前を指定しないと、RegisterInstanceで名前を指定せず登録されたもののうち、最後に指定されたものを使用する。
[Dependency]
public IAnimal Pet { get; set; }