私はMSDNでUnityに関する記事(Dependency Injection、Inversion of Control)を読んできましたが、簡単な用語(または簡単な例)で説明する必要があると思います。私はMVPCパターンに精通しています(ここで使用しています)が、まだこのUnityのことを本当に把握できていないため、アプリケーション設計の次のステップだと思います。
UnityはIoCの「コンテナ」にすぎません。 Google StructureMapを試してみてください。 IoCが初めての場合は、少し簡単に理解できると思います。
基本的に、IoCを理解すれば、オブジェクトの作成時にコントロールを反転していることを理解できます。
IoCなし:
public class MyClass
{
IMyService _myService;
public MyClass()
{
_myService = new SomeConcreteService();
}
}
IoCコンテナーの場合:
public class MyClass
{
IMyService _myService;
public MyClass(IMyService myService)
{
_myService = myService;
}
}
IoCがなければ、IMyServiceに依存するクラスは、使用するサービスの具体的なバージョンを新しくする必要があります。そして、それはいくつかの理由で悪いです(クラスをIMyServiceの特定の具体的なバージョンに結合した、簡単に単体テストを行えない、簡単に変更できないなど)
IoCコンテナーを使用すると、コンテナーを「構成」して、これらの依存関係を解決します。そのため、コンストラクターベースのインジェクションスキームでは、IMyService依存関係へのインターフェイスをコンストラクターに渡すだけです。コンテナでMyClassを作成すると、コンテナはIMyServiceの依存関係を解決します。
StructureMapを使用して、コンテナを構成すると次のようになります。
StructureMapConfiguration.ForRequestedType<MyClass>().TheDefaultIsConcreteType<MyClass>();
StructureMapConfiguration.ForRequestedType<IMyService>().TheDefaultIsConcreteType<SomeConcreteService>();
そのため、コンテナに「誰かがIMyServiceを要求したら、SomeConcreteServiceのコピーを渡してください」と伝えます。また、誰かがMyClassを要求すると、具体的なMyClassを取得するように指定しました。
これがIoCコンテナーが実際に行うすべてです。彼らはもっと多くのことができますが、それが推力です-彼らはあなたのために依存関係を解決するので、あなたはする必要はありません(そしてあなたはあなたのコード全体で「新しい」キーワードを使用する必要はありません)。
最終ステップ:MyClassを作成するとき、次のようにします。
var myClass = ObjectFactory.GetInstance<MyClass>();
それが役に立てば幸いです。私にメールしてください。
David Haydenによる30分間のUnity Dependency Injection IoC Screencastを見て、それが例で説明できると感じました。ショーノートの抜粋を次に示します。
スクリーンキャストは、Unity IoCの一般的な使用方法をいくつか示しています。
Unityは他の多くのライブラリと同様に、自分で作成しなくても要求されたタイプのインスタンスを取得できるライブラリです。与えられた。
public interface ICalculator
{
void Add(int a, int b);
}
public class Calculator : ICalculator
{
public void Add(int a, int b)
{
return a + b;
}
}
Unityなどのライブラリを使用して、タイプICalculator(別名IoC(制御の反転))が要求されたときに返される計算機を登録します(この例は理論的であり、技術的には正しくありません)。
IoCLlibrary.Register<ICalculator>.Return<Calculator>();
したがって、ICalculatorのインスタンスが必要な場合は...
Calculator calc = IoCLibrary.Resolve<ICalculator>();
IoCライブラリは通常、タイプを解決するたびにシングルトンを保持するか、新しいインスタンスを作成するように構成できます。
ICalculatorに依存して存在する可能性のあるクラスがあるとしましょう。
public class BankingSystem
{
public BankingSystem(ICalculator calc)
{
_calc = calc;
}
private ICalculator _calc;
}
また、作成時にオブジェクトをコンストラクタに注入するようにライブラリをセットアップできます。
したがって、DIまたは依存性注入とは、別のオブジェクトが必要とする可能性のあるオブジェクトを注入することです。
この男WilcoxTutorialsは、初心者向けのUnityコンテナーの優れたデモンストレーションを提供します。
パート1: http://www.youtube.com/watch?v=CWwe9Z0Gyew
パート2: http://www.youtube.com/watch?v=PsIbevgzQQE
30分以内で、基本を理解できます!
UnityはIoCです。 IoCのポイントは、型自体の外側の型間の依存関係の配線を抽象化することです。これにはいくつかの利点があります。まず第一に、それは集中的に行われます。つまり、依存関係が変更されたときに多くのコードを変更する必要はありません(ユニットテストの場合があります)。
さらに、コードの代わりに構成データを使用して配線が行われた場合、展開後に依存関係を実際に再配線し、コードを変更せずにアプリケーションの動作を変更できます。
MSDNには nityを使用した依存性注入の開発者ガイド があります。
開発者ガイドは、依存性注入とは何かの基本から始まり、依存性注入にUnityを使用する方法の例を続けています。 2014年2月の時点で、開発者ガイドはUnity 3.0をカバーしており、2013年4月にリリースされました。
ASP.NET Web API 2の依存性注入のほとんどの例を取り上げています
public interface IShape
{
string Name { get; set; }
}
public class NoShape : IShape
{
public string Name { get; set; } = "I have No Shape";
}
public class Circle : IShape
{
public string Name { get; set; } = "Circle";
}
public class Rectangle : IShape
{
public Rectangle(string name)
{
this.Name = name;
}
public string Name { get; set; } = "Rectangle";
}
DIAutoV2Controller.csでは、自動注入メカニズムが使用されます
[RoutePrefix("api/v2/DIAutoExample")]
public class DIAutoV2Controller : ApiController
{
private string ConstructorInjected;
private string MethodInjected1;
private string MethodInjected2;
private string MethodInjected3;
[Dependency]
public IShape NoShape { get; set; }
[Dependency("Circle")]
public IShape ShapeCircle { get; set; }
[Dependency("Rectangle")]
public IShape ShapeRectangle { get; set; }
[Dependency("PiValueExample1")]
public double PiValue { get; set; }
[InjectionConstructor]
public DIAutoV2Controller([Dependency("Circle")]IShape shape1, [Dependency("Rectangle")]IShape shape2, IShape shape3)
{
this.ConstructorInjected = shape1.Name + " & " + shape2.Name + " & " + shape3.Name;
}
[NonAction]
[InjectionMethod]
public void Initialize()
{
this.MethodInjected1 = "Default Initialize done";
}
[NonAction]
[InjectionMethod]
public void Initialize2([Dependency("Circle")]IShape shape1)
{
this.MethodInjected2 = shape1.Name;
}
[NonAction]
[InjectionMethod]
public void Initialize3(IShape shape1)
{
this.MethodInjected3 = shape1.Name;
}
[HttpGet]
[Route("constructorinjection")]
public string constructorinjection()
{
return "Constructor Injected: " + this.ConstructorInjected;
}
[HttpGet]
[Route("GetNoShape")]
public string GetNoShape()
{
return "Property Injected: " + this.NoShape.Name;
}
[HttpGet]
[Route("GetShapeCircle")]
public string GetShapeCircle()
{
return "Property Injected: " + this.ShapeCircle.Name;
}
[HttpGet]
[Route("GetShapeRectangle")]
public string GetShapeRectangle()
{
return "Property Injected: " + this.ShapeRectangle.Name;
}
[HttpGet]
[Route("GetPiValue")]
public string GetPiValue()
{
return "Property Injected: " + this.PiValue;
}
[HttpGet]
[Route("MethodInjected1")]
public string InjectionMethod1()
{
return "Method Injected: " + this.MethodInjected1;
}
[HttpGet]
[Route("MethodInjected2")]
public string InjectionMethod2()
{
return "Method Injected: " + this.MethodInjected2;
}
[HttpGet]
[Route("MethodInjected3")]
public string InjectionMethod3()
{
return "Method Injected: " + this.MethodInjected3;
}
}
DIV2Controller.csでは、すべてがDependency Configuration Resolverクラスから注入されます
[RoutePrefix("api/v2/DIExample")]
public class DIV2Controller : ApiController
{
private string ConstructorInjected;
private string MethodInjected1;
private string MethodInjected2;
public string MyPropertyName { get; set; }
public double PiValue1 { get; set; }
public double PiValue2 { get; set; }
public IShape Shape { get; set; }
// MethodInjected
[NonAction]
public void Initialize()
{
this.MethodInjected1 = "Default Initialize done";
}
// MethodInjected
[NonAction]
public void Initialize2(string myproperty1, IShape shape1, string myproperty2, IShape shape2)
{
this.MethodInjected2 = myproperty1 + " & " + shape1.Name + " & " + myproperty2 + " & " + shape2.Name;
}
public DIV2Controller(string myproperty1, IShape shape1, string myproperty2, IShape shape2)
{
this.ConstructorInjected = myproperty1 + " & " + shape1.Name + " & " + myproperty2 + " & " + shape2.Name;
}
[HttpGet]
[Route("constructorinjection")]
public string constructorinjection()
{
return "Constructor Injected: " + this.ConstructorInjected;
}
[HttpGet]
[Route("PropertyInjected")]
public string InjectionProperty()
{
return "Property Injected: " + this.MyPropertyName;
}
[HttpGet]
[Route("GetPiValue1")]
public string GetPiValue1()
{
return "Property Injected: " + this.PiValue1;
}
[HttpGet]
[Route("GetPiValue2")]
public string GetPiValue2()
{
return "Property Injected: " + this.PiValue2;
}
[HttpGet]
[Route("GetShape")]
public string GetShape()
{
return "Property Injected: " + this.Shape.Name;
}
[HttpGet]
[Route("MethodInjected1")]
public string InjectionMethod1()
{
return "Method Injected: " + this.MethodInjected1;
}
[HttpGet]
[Route("MethodInjected2")]
public string InjectionMethod2()
{
return "Method Injected: " + this.MethodInjected2;
}
}
依存関係リゾルバーの構成
public static void Register(HttpConfiguration config)
{
var container = new UnityContainer();
RegisterInterfaces(container);
config.DependencyResolver = new UnityResolver(container);
// Other Web API configuration not shown.
}
private static void RegisterInterfaces(UnityContainer container)
{
var dbContext = new SchoolDbContext();
// Registration with constructor injection
container.RegisterType<IStudentRepository, StudentRepository>(new InjectionConstructor(dbContext));
container.RegisterType<ICourseRepository, CourseRepository>(new InjectionConstructor(dbContext));
// Set constant/default value of Pi = 3.141
container.RegisterInstance<double>("PiValueExample1", 3.141);
container.RegisterInstance<double>("PiValueExample2", 3.14);
// without a name
container.RegisterInstance<IShape>(new NoShape());
// with circle name
container.RegisterType<IShape, Circle>("Circle", new InjectionProperty("Name", "I am Circle"));
// with rectangle name
container.RegisterType<IShape, Rectangle>("Rectangle", new InjectionConstructor("I am Rectangle"));
// Complex type like Constructor, Property and method injection
container.RegisterType<DIV2Controller, DIV2Controller>(
new InjectionConstructor("Constructor Value1", container.Resolve<IShape>("Circle"), "Constructor Value2", container.Resolve<IShape>()),
new InjectionMethod("Initialize"),
new InjectionMethod("Initialize2", "Value1", container.Resolve<IShape>("Circle"), "Value2", container.Resolve<IShape>()),
new InjectionProperty("MyPropertyName", "Property Value"),
new InjectionProperty("PiValue1", container.Resolve<double>("PiValueExample1")),
new InjectionProperty("Shape", container.Resolve<IShape>("Rectangle")),
new InjectionProperty("PiValue2", container.Resolve<double>("PiValueExample2")));
}