05 | 依赖注入:良好架构的起点


为什么要使用依赖注入框架

  • 依赖注入框架其实也就是我们通常所说的IOC框架,这个框架可以帮助我们来管理类与类之间的依赖关系。
  • 借助依赖注入框架,我们可以轻松管理类之间的依赖,帮助我们在构建应用时遵循设计原则,确保代码的可维护性和可扩展性。
  • ASP.NET Core的整个架构中,依赖注入框架提供了对象创建和生命周期管理的核心能力,各个组件相互协作,也是由依赖注入框架的能力来实现的。

核心组件包

  • 用了一个经典的设计模式,叫做接口实现分离模式
  • Microsoft.Extensions.DependencyInjection.Abstracions (抽象包)
  • Microsoft.Extensions.DependencyInjection (具体实现)

依赖注入框架的核心类型

  • IServiceCollection
    • 负责服务的注册
  • ServiceDescriptor
    • 每一个服务注册时的信息
  • IServiceProvide
    • 具体的容器也是由ServiceCollection Build出来的
  • IServiceScope
    • 表示一个容器的子容器的生命周期

生命周期:ServiceLifetime

  • 单例 Singleton
    • 在整个根容器的生命周期内都是单例,不论根容器还是子容器,与作用域的区别就是一个是全局的,一个是范围的。
  • 作用域 Scoped
    • 在我的Scope的生存周期内也就是容器的生存周期内,或者子容器的生存周期内,如果我的容器释放掉,那就意味着我的对象也会释放掉。在这个范围内的话,我们得到是一个单例模式。
  • 瞬时(暂时) Transient
    • 每一次去从容器里面获取对象时,都可以得到一个全新的对象

首先我们新建Web程序??选择API模板

public void ConfigureServices(IServiceCollection services)
{
    #region 注册服务不同的生命周期
    // 单例
    services.AddSingleton();
    // 作用域
    services.AddScoped();
    // 瞬时
    services.AddTransient();

    #endregion
	
	#region 花式注册
	// 自己创建对象
	services.AddSingleton(new OrderService());
    // 工厂
    services.AddSingleton(serviceProvider =>
	{
		return new OrderService();
	});
    services.AddSingleton(serviceProvider =>
    {
		return new OrderService();
	});
    #endregion

	#region 尝试注册
	//如果发现已经注册过了就不注册
	services.TryAddSingleton();
    //将不同实现的实例注册进去
    services.TryAddEnumerable(ServiceDescriptor.Singleton());

    #endregion

    #region 移除和替换注册
    services.RemoveAll();
    services.Replace(ServiceDescriptor.Singleton());
    #endregion

    #region 注册泛型模板
	services.AddSingleton(typeof(IGenericService<>),typeof(GenericService<>));
    #endregion

	services.AddControllers();
}
// 两种获取到实例的方式

// 1.通过构造函数的方式
public WeatherForecastController(ILogger logger,IOrderService orderService,IGenericService genericService)
{
    _logger = logger;
}

// 2.通过[FormServices]
public int GetServiceList([FromServices]IEnumerable services)
{
    foreach (var item in services)
    {
        Console.WriteLine($"获取到服务实例:{item}:{item.GetHashCode()}");
    }
    return 1;
}
// 这两种方式的使用场景时不同的,当我们定义个Conllection的时候,它的服务时大部分接口都需要使用的情况下,
// 推荐的做法时用构造函数的注入方式。
// 如果说时我们这个服务仅仅是在某一个接口使用的情况下,
// 推荐使用[FromServices]的方式来注入。