C# .NET 5.0 依赖注入

参考:

https://www.cnblogs.com/zoro-zero/p/13490459.html

https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1

DI:是一种软件设计模式,Asp.net core支持该模式。这是一种在类及其依赖关系之间实现控制反转 (IoC) 的技术。

依赖项:指另一个对象所依赖的对象。

常见的DI框架:Autofac、Unity......

依赖关系注入概述——  谁依赖谁,将谁注入谁

依赖注入是指在创建一个对象时,自动地创建它所依赖的对象,并注入。

依赖注入的方式:1.构造方法注入;  2.Set方法注入;  3.方法参数注入

1.构造方法注入:

优点:

  • 在构造方法中体现出对其他类的依赖,直接就可以看出这个类所需要的依赖那些类才能工作。
  • 脱离了IOC框架,这个类仍然可以工作。
  • 一旦对象初始化成功了,这个对象的状态肯定是正确的。

缺点:

  • 构造函数会有很多参数(Bad smell)。
  • 有些类是需要默认构造函数的,比如MVC框架的Controller类,一旦使用构造函数注入,就无法使用默认构造函数。
  • 这个类里面的有些方法并不需要用到这些依赖(Bad smell)。

2.Set方法注入

优点:
  • 在对象的整个生命周期内,可以随时动态的改变依赖。
  • 非常灵活。
缺点:
  • 对象在创建后,被设置依赖对象之前这段时间状态是不对的。
  • 不直观,无法清晰地表示哪些属性是必须的。

3.方法参数注入--即以入参的方法,将对象赋值给方法内的对象

方法参数注入的意思是在创建对象后,通过自动调用某个方法来注入依赖。类似如下代码:

public class MovieRecommender {
 
 private MovieCatalog movieCatalog;
 public class MovieRecommender {
 
  private MovieCatalog movieCatalog;
 
  private CustomerPreferenceDao customerPreferenceDao;
 
  @Autowired
  public void prepare(MovieCatalog movieCatalog,
                      CustomerPreferenceDao customerPreferenceDao) {
      this.movieCatalog = movieCatalog;
      this.customerPreferenceDao = customerPreferenceDao;
  }
 
  // ...
}
  private CustomerPreferenceDao customerPreferenceDao;
 
  public void prepare(MovieCatalog movieCatalog,
                      CustomerPreferenceDao customerPreferenceDao) {
      this.movieCatalog = movieCatalog;
      this.customerPreferenceDao = customerPreferenceDao;
  }
 
  // ...
}
一般只有一个方法依赖到注入的对象时用到
如果有多个方法依赖到注入的对象,还是使用构造方法注入方式比较合适
优点:
  • 比较灵活。
缺点:
  • 新加入依赖时会破坏原有的方法签名,如果这个方法已经被其他很多模块用到就很麻烦。
  • 与构造方法注入一样,会有很多参数。

依赖注入使用注意事项:

1.使用接口或基类将依赖关系实现抽象化

2.在服务容器中注册依赖关系。 ASP.NET Core 提供了一个内置的服务容器 IServiceProvider。 服务通常已在应用的 Startup.ConfigureServices 方法中注册。

3.将服务注入到使用它的类的构造函数中。 框架负责创建依赖关系的实例,并在不再需要时将其释放。

如下所示:

using System;

namespace Models
{
    public interface IMyDependency
    {
        void WriteMessage(string message);
    }
}

using System;

namespace Models
{
    /// <summary>
    /// 示例应用使用具体类型 MyDependency 注册 IMyDependency 服务
    /// </summary>
    public class MyDependency : IMyDependency
    {
        /// <summary>
        /// 传参注入
        /// </summary>
        /// <param name="message">依赖项</param>
        public void WriteMessage(string message)
        {
            Console.WriteLine($"MyDependency.WriteMessage Message: {message}");
        }
    }
}
注:以上示例应用使用具体类型 MyDependency 注册 IMyDependency 服务;
AddScoped 方法使用范围内生存期(单个请求的生存期)注册服务
public void ConfigureServices(IServiceCollection services)
{ 
  services.AddScoped<IMyDependency, MyDependency>(); services.AddRazorPages(); 
}
在示例应用中,请求 IMyDependency 服务并用于调用 WriteMessage 方法:
namespace Models.Model.Demo1
{
    public class OneModel
    {
        private readonly IMyDependency _myDependency;
        public OneModel(IMyDependency myDependency)
        {
            _myDependency = myDependency;
        }

        public void OnGet()
        {
            _myDependency.WriteMessage("OneModel.OnGet");
        }
    }
}

通过使用 DI 模式,表示控制器:

  • 不使用具体类型 MyDependency,仅使用它实现的 IMyDependency 接口。 这样可以轻松地更改控制器使用的实现,而无需修改控制器。
  • 不创建 MyDependency 的实例,这由 DI 容器创建。

可以通过使用内置日志记录 API 来改善 IMyDependency 接口的实现:using Microsoft.Extensions.Logging;

namespace Models.Model.Demo1
{
    public class MyDependency2 : IMyDependency
    {
        private readonly ILogger<MyDependency2> _logger;
        /// <summary>
        /// 构造注入
        /// </summary>
        /// <param name="logger">依赖项</param>
        public MyDependency2(ILogger<MyDependency2> logger)
        {
            _logger = logger;
        }
        /// <summary>
        /// 传参注入
        /// </summary>
        /// <param name="message">依赖项</param>
        public void WriteMessage(string message)
        {
            _logger.LogInformation($"MyDependency2.WriteMessage Message: {message}");
        }
    }
}

更新的 ConfigureServices 方法注册新的 IMyDependency 实现:
public void ConfigureServices(IServiceCollection services) 
{ 
  services.AddScoped<IMyDependency, MyDependency2>(); 
}
MyDependency2 依赖于 ILogger<TCategoryName>,并在构造函数中对其进行请求。 ILogger<TCategoryName> 是框架提供的服务
必须被解析的依赖关系的集合通常被称为“依赖关系树”、“依赖关系图”或“对象图”

容器通过利用(泛型)开放类型解析 ILogger<TCategoryName>,而无需注册每个(泛型)构造类型

在依赖项注入术语中,服务:

  • 通常是向其他对象提供服务的对象,如 IMyDependency 服务。
  • 与 Web 服务无关,尽管服务可能使用 Web 服务。

  

  

博客内容主要用于日常学习记录,内容比较随意,如有问题,还需谅解!!!
原文地址:https://www.cnblogs.com/YYkun/p/15594585.html