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

除了使用泛型的方式注册服务之外,还有其他的方式

添加一个 OrderService

public interface IOrderService
{

}

public class OrderService1 : IOrderService
{

}


public class OrderService2 : IOrderService
{

}


在 Startup 中注册服务

public void ConfigureServices(IServiceCollection services)
{
#region 注册服务不同生命周期的服务

// 将单例的服务注册为单例的模式
services.AddSingleton<IMySingletonService, MySingletonService>();

// Scoped 的服务注册为 Scoped 的生命周期
services.AddScoped<IMyScopedService, MyScopedService>();

// 瞬时的服务注册为瞬时的生命周期
services.AddTransient<IMyTransientService, MyTransientService>();

#endregion

#region 花式注册

services.AddSingleton<IOrderService>(new OrderService1()); //直接注入实例

#endregion

#region 尝试注册(如果服务已经注册过,则不再注册)

services.TryAddSingleton<IOrderService, OrderService2>();

#endregion

services.AddControllers();
}


在服务端 WeatherForecastController 定义另外一个接口

// IEnumerable<IOrderService>:获取曾经注册过的所有 IOrderService
public int GetServiceList([FromServices]IEnumerable<IOrderService> services)
{
foreach (var item in services)
{
Console.WriteLine($"获取到服务实例:{item.ToString()}:{item.GetHashCode()}");
}
return 1;
}


调整一下程序的启动页面,Properties 下的 launchSetting.json 的这一行代码

"launchUrl": "weatherforecast/getservicelist",


修改路由

[Route("[controller]/[action]")]
public class WeatherForecastController : ControllerBase


启动程序,输出如下:

获取到服务实例:DependencyInjectionDemo.Services.OrderService1:25560520


只有一个实例,说明 TryAddSingleton 没有生效

接着,注册两个服务

services.AddSingleton<IOrderService>(new OrderService1());
services.AddSingleton<IOrderService, OrderService2>();


启动程序,输出如下:

获取到服务实例:DependencyInjectionDemo.Services.OrderService1:16991442
获取到服务实例:DependencyInjectionDemo.Services.OrderService2:25560520


结果获取到了两个实例

接下来,了解一下 TryAddEnumerable 与 TryAddSingleton 的区别

#region 尝试注册(如果服务已经注册过,则不再注册)

services.TryAddSingleton<IOrderService, OrderService2>();// 接口类型重复,则不注册
services.TryAddEnumerable(ServiceDescriptor.Singleton<IOrderService, OrderService1>());// 相同类型的接口,实现类相同,则不注册

#endregion


注册服务

services.AddSingleton<IOrderService>(new OrderService1());
services.TryAddEnumerable(ServiceDescriptor.Singleton<IOrderService, OrderService1>());


启动程序,输出如下:

获取到服务实例:DependencyInjectionDemo.Services.OrderService1:53046438


因为已经注册过 OrderService,所以第二句代码不生效

以不同的实现注册服务

services.AddSingleton<IOrderService>(new OrderService1());
services.TryAddEnumerable(ServiceDescriptor.Singleton<IOrderService, OrderService2>());


启动程序,输出如下:

获取到服务实例:DependencyInjectionDemo.Services.OrderService1:24219861
获取到服务实例:DependencyInjectionDemo.Services.OrderService2:38855053


这样就可以获取到两个服务实例

刷新浏览器,再执行一遍

获取到服务实例:DependencyInjectionDemo.Services.OrderService1:24219861
获取到服务实例:DependencyInjectionDemo.Services.OrderService2:38855053
获取到服务实例:DependencyInjectionDemo.Services.OrderService1:24219861
获取到服务实例:DependencyInjectionDemo.Services.OrderService2:38855053


因为注册的是单例,所以两次请求获取到的实例都是相同的

这样做的好处是:一方面避免一个服务重复注册,也可以控制一个服务需要注册不同的实现

.NET Core开发实战(第5课:依赖注入:良好架构的起点)--学习笔记(中)_商业

.NET Core开发实战(第5课:依赖注入:良好架构的起点)--学习笔记(中)_商业_02