本節目錄
DI介紹
控制反轉(Inversion of Control,英文縮寫為IoC)是一個重要的面向對象編程的法則來削減計算機程序的耦合問題.
依賴注入(Dependency Injection,英文縮寫為DI)是一種設計模式.
其實本質都是指同一件事,強調的內容不一樣.IoC強調容器的作用,DI強調注入的作用.
通常IoC和DI可以理解為一個意思,只是指的對象不同.
DI基本原理
DI本質上是通過容器來反射創建實例.
1個簡單的類
class Person
{
public void Say()
{
Console.WriteLine("Person's say method is Called");
}
}
反射代碼(className:類的全限定名)
private static object CreateInstance(Assembly assembly, string className)
{
var type = assembly.GetType(className);
return type != null ? Activator.CreateInstance(type) : null;
}
執行(XX為命名空間)
static void Main(string[] args)
{
var obj = CreateInstance(Assembly.GetExecutingAssembly(), "XX.Person");
var person = obj as Person;
if (person != null)
{
person.Say();
}
Console.ReadKey();
}
在上面能看到1個問題,一般情況下.既然使用DI,就不知道具體的注入對象.所以強調面向接口編程.
所以實際上一般先定義接口,再通過DI容器創建對象.
interface IPerson
{
void Say();
}
class Person : IPerson
{
public void Say()
{
Console.WriteLine("Person's say method is Called");
}
}
執行
static void Main(string[] args)
{
var obj = CreateInstance(Assembly.GetExecutingAssembly(), "Demo.Person");
var person = obj as IPerson;
if (person != null)
{
person.Say();
}
Console.ReadKey();
}
DI框架
DI框架流行的有Castle Windsor,Unity...(Autofac Spring.Net已經聊過,不再演示)
在DI框架中,一般需要將對象注冊到容器中,然后從容器解析出來.
Castle
Install-Package Castle.Windsor
待注入類
interface ITransient
{
}
interface IPerson
{
void Say();
}
class Person : IPerson, ITransient
{
public void Say()
{
Console.WriteLine("Person's say method is Called");
}
}
注冊解析方式一
static void Main(string[] args)
{
using (var container = new WindsorContainer())
{
container.Register(Component.For<Person, IPerson>());
var person = container.Resolve<IPerson>();
person.Say();
}
Console.ReadKey();
}
注冊解析方式二
public class AssmInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly() //選擇Assembly
.IncludeNonPublicTypes() //約束Type
.BasedOn<ITransient>() //約束Type
.WithService.DefaultInterfaces() //匹配類型
.LifestyleTransient()); //注冊生命周期
}
}
static void Main(string[] args)
{
using (var container = new WindsorContainer())
{
container.Install(new AssmInstaller());
var person = container.Resolve<IPerson>();
person.Say();
}
Console.ReadKey();
}
構造函數注入
class Task : ITransient
{
public IPerson Person { get; set; }
public Task(IPerson person)
{
Person = person;
Person.Say();
}
}
static void Main(string[] args)
{
using (var container = new WindsorContainer())
{
container.Install(new AssmInstaller());
container.Resolve<Task>();
}
Console.ReadKey();
}
屬性注入
class Task : ITransient
{
public IPerson Person { get; set; }
public Task()
{
}
public void Say()
{
Person.Say();
}
}
static void Main(string[] args)
{
using (var container = new WindsorContainer())
{
container.Install(new AssmInstaller());
container.Resolve<Task>().Say();
}
Console.ReadKey();
}
MVC集成
Install-Package Castle.Windsor.Mvc
Application_Start注冊
protected void Application_Start()
{
RouteConfig.RegisterRoutes(RouteTable.Routes);
var container = new WindsorContainer()
.Install(FromAssembly.This());
var controllerFactory = new WindsorControllerFactory(container.Kernel);
ControllerBuilder.Current.SetControllerFactory(controllerFactory);
}
Installer注冊
public class AssmInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly()
.IncludeNonPublicTypes()
.BasedOn<ITransient>()
.WithService.DefaultInterfaces()
.LifestyleTransient());
container.Register(Classes.FromThisAssembly()
.BasedOn<Controller>()
.LifestyleTransient()
);
}
}
這樣Castle Windsor就能接管解析Controller了.
Unity
Install-Package Unity
待注入類
public interface IPerson
{
void Say();
}
public class Person : IPerson
{
public void Say()
{
Console.WriteLine("Person's say method is Called");
}
}
注冊解析一
static void Main(string[] args)
{
using (var container = new UnityContainer())
{
container.RegisterType<IPerson, Person>(new TransientLifetimeManager());
var person = container.Resolve<IPerson>();
person.Say();
}
Console.ReadKey();
}
注冊解析二
static void Main(string[] args)
{
using (var container = new UnityContainer())
{
container.RegisterInstance<IPerson>(new Person());
var person = container.Resolve<IPerson>();
person.Say();
}
Console.ReadKey();
}
構造函數注入
class Task : ITask
{
public IPerson Person { get; set; }
public Task(IPerson person)
{
Person = person;
Person.Say();
}
}
public interface ITask
{
}
static void Main(string[] args)
{
using (var container = new UnityContainer())
{
container.RegisterInstance<IPerson>(new Person());
container.RegisterType<ITask, Task>();
container.Resolve<ITask>();
}
Console.ReadKey();
}
屬性注入
class Task : ITask
{
[Dependency]
public IPerson Person { get; set; }
public Task(IPerson person)
{
Person = person;
}
public void Say()
{
Person.Say();
}
}
static void Main(string[] args)
{
using (var container = new UnityContainer())
{
container.RegisterInstance<IPerson>(new Person());
container.RegisterType<ITask, Task>();
var task = container.Resolve<ITask>();
task.Say();
}
Console.ReadKey();
}
MVC集成
Install-Package Unity.Mvc
Application_Start注冊
protected void Application_Start()
{
RouteConfig.RegisterRoutes(RouteTable.Routes);
var container = new UnityContainer();
container.RegisterType<IPerson, Person>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
這樣Unity就接管了Controller的創建
