DI介绍
控制反转(Inversion of Control,英文缩写为IoC)是一个重要的面向对象编程的法则来削减计算机程序的耦合问题.
依赖注入(Dependency Injection,英文缩写为DI)是一种设计模式.
其实本质都是指同一件事,强调的内容不一样.IoC强调容器的作用,DI强调注入的作用.
通常IoC和DI可以理解为一个意思,只是指的对象不同.
DI基本原理
DI本质上是通过容器来反射创建实例.
1个简单的类
1
2
3
4
5
6
7
|
class Person
{
public void Say()
{
Console.WriteLine( "Person's say method is Called" );
}
}
|
反射代码(className:类的全限定名)
1
2
3
4
5
|
private static object CreateInstance(Assembly assembly, string className)
{
var type = assembly.GetType(className);
return type != null ? Activator.CreateInstance(type) : null ;
}
|
执行(XX为命名空间)
1
2
3
4
5
6
7
8
9
10
|
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容器创建对象.
1
2
3
4
5
6
7
8
9
10
11
|
interface IPerson
{
void Say();
}
class Person : IPerson
{
public void Say()
{
Console.WriteLine( "Person's say method is Called" );
}
}
|
执行
1
2
3
4
5
6
7
8
9
10
|
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
待注入类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
interface ITransient
{
}
interface IPerson
{
void Say();
}
class Person : IPerson, ITransient
{
public void Say()
{
Console.WriteLine( "Person's say method is Called" );
}
}
|
注册解析方式一
1
2
3
4
5
6
7
8
9
10
|
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();
}
|
注册解析方式二
1
2
3
4
5
6
7
8
9
10
11
|
public class AssmInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly() //选择Assembly
.IncludeNonPublicTypes() //约束Type
.BasedOn<ITransient>() //约束Type
.WithService.DefaultInterfaces() //匹配类型
.LifestyleTransient()); //注册生命周期
}
}
|
1
2
3
4
5
6
7
8
9
10
|
static void Main( string [] args)
{
using ( var container = new WindsorContainer())
{
container.Install( new AssmInstaller());
var person = container.Resolve<IPerson>();
person.Say();
}
Console.ReadKey();
}
|
构造函数注入
1
2
3
4
5
6
7
8
9
|
class Task : ITransient
{
public IPerson Person { get ; set ; }
public Task(IPerson person)
{
Person = person;
Person.Say();
}
}
|
1
2
3
4
5
6
7
8
9
|
static void Main( string [] args)
{
using ( var container = new WindsorContainer())
{
container.Install( new AssmInstaller());
container.Resolve<Task>();
}
Console.ReadKey();
}
|
属性注入
1
2
3
4
5
6
7
8
9
10
11
|
class Task : ITransient
{
public IPerson Person { get ; set ; }
public Task()
{
}
public void Say()
{
Person.Say();
}
}
|
1
2
3
4
5
6
7
8
9
|
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注册
1
2
3
4
5
6
7
8
|
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注册
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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
待注入类
1
2
3
4
5
6
7
8
9
10
11
|
public interface IPerson
{
void Say();
}
public class Person : IPerson
{
public void Say()
{
Console.WriteLine( "Person's say method is Called" );
}
}
|
注册解析一
1
2
3
4
5
6
7
8
9
10
|
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();
}
|
注册解析二
1
2
3
4
5
6
7
8
9
10
|
static void Main( string [] args)
{
using ( var container = new UnityContainer())
{
container.RegisterInstance<IPerson>( new Person());
var person = container.Resolve<IPerson>();
person.Say();
}
Console.ReadKey();
}
|
构造函数注入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class Task : ITask
{
public IPerson Person { get ; set ; }
public Task(IPerson person)
{
Person = person;
Person.Say();
}
}
public interface ITask
{
}
|
1
2
3
4
5
6
7
8
9
10
|
static void Main( string [] args)
{
using ( var container = new UnityContainer())
{
container.RegisterInstance<IPerson>( new Person());
container.RegisterType<ITask, Task>();
container.Resolve<ITask>();
}
Console.ReadKey();
}
|
属性注入
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Task : ITask
{
[Dependency]
public IPerson Person { get ; set ; }
public Task(IPerson person)
{
Person = person;
}
public void Say()
{
Person.Say();
}
}
|
1
2
3
4
5
6
7
8
9
10
11
|
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注册
1
2
3
4
5
6
7
|
protected void Application_Start()
{
RouteConfig.RegisterRoutes(RouteTable.Routes);
var container = new UnityContainer();
container.RegisterType<IPerson, Person>();
DependencyResolver.SetResolver( new UnityDependencyResolver(container));
}
|
这样Unity就接管了Controller的创建