[Solution] DI原理解析及CastleUnity框架使用

Posted 叶祖辉

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Solution] DI原理解析及CastleUnity框架使用相关的知识,希望对你有一定的参考价值。

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 { getset; }

    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 { getset; }

    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 { getset; }

    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 { getset; }

    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的创建

 

以上是关于[Solution] DI原理解析及CastleUnity框架使用的主要内容,如果未能解决你的问题,请参考以下文章

DI 原理解析 并实现一个简易版 DI 容器

Spring系列之手写一个SpringMVC

JavaScript中实现DI的原理

Spring系列之AOP的原理及手动实现

Spring IOC 原理深层解析

Spring MVC工作原理及源码解析 ViewResolver实现原理及源码解析