[Solution] DI原理解析及Castle、Unity框架使用

本节目录

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

posted @   Never、C  阅读(1682)  评论(5编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示