Unityに関するMSDNの記事(依存性注入、制御の反転)を読んでいますが、簡単な用語(または簡単な例)で説明する必要があると思います。私はMVPCパターンに精通しています(ここではそれを使用しています)が、まだこのUnityのことを本当に理解できていないので、アプリケーション設計の次のステップだと思います。
Unityに関するMSDNの記事(依存性注入、制御の反転)を読んでいますが、簡単な用語(または簡単な例)で説明する必要があると思います。私は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コンテナが実際に行うことはこれだけです。彼らはもっと多くのことができますが、それが目的です-依存関係を解決するので、あなたはする必要がありません(そして、コード全体で "new"キーワードを使用する必要はありません)。
最後のステップ: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のようなライブラリを使用して、ICalcタイプ(IoC(Inversion of Control))が要求されたときに返されるCalculatorを登録します(この例は理論上のものであり、技術的に正しくありません)。
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には、Unityを使用した依存性注入に関する開発者ガイドがあります便利なをがあります。
開発者ガイドは、依存性注入とは何かという基本から始まり、Unityを使用して依存性注入を行う例を示します。2014年2月の時点で、開発者ガイドは2013年4月にリリースされたUnity 3.0をカバーしています。
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")));
}