5:依赖注入:良好架构的起点(中)
.NET Core开发实战前文传送门:
05 | 依赖注入:良好架构的起点
除了使用泛型的方式注册服务之外,还有其他的方式
添加一个 OrderService
public interface IOrderService { } public class OrderService : IOrderService { } public class OrderServiceEx : 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 OrderService()); //直接注入实例 //// 通过工厂模式 //services.AddSingleton<IOrderService>(serviceProvider => //{ // return new OrderServiceEx(); //}); //services.AddScoped<IOrderService>(serviceProvider => //{ // // 可以使用 IServiceProvider 入参,也就意味着可以从容器里面获取多个对象,进行组装,得到最终的实现实例 // // 也就是可以把工厂类设计的比较复杂,比如说实现类依赖了容器里面的另外一个类,或者用另一个类来包装原有的实现 // //serviceProvider.GetService<>() // return new OrderServiceEx(); //}); #endregion #region 尝试注册(如果服务已经注册过,则不再注册) services.TryAddSingleton<IOrderService, OrderServiceEx>(); #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",
启动程序,输出如下:
获取到服务实例:DependencyInjectionDemo.Services.OrderService:25560520
只有一个实例,说明 TryAddSingleton 没有生效
接着,注册两个服务
services.AddSingleton<IOrderService>(new OrderService()); services.AddSingleton<IOrderService, OrderServiceEx>();
启动程序,输出如下:
获取到服务实例:DependencyInjectionDemo.Services.OrderService:16991442 获取到服务实例:DependencyInjectionDemo.Services.OrderServiceEx:25560520
结果获取到了两个实例
接下来,了解一下 TryAddEnumerable 与 TryAddSingleton 的区别
#region 尝试注册(如果服务已经注册过,则不再注册) services.TryAddSingleton<IOrderService, OrderServiceEx>();// 接口类型重复,则不注册 services.TryAddEnumerable(ServiceDescriptor.Singleton<IOrderService, OrderService>());// 相同类型的接口,实现类相同,则不注册 #endregion
注册服务
services.AddSingleton<IOrderService>(new OrderService()); services.TryAddEnumerable(ServiceDescriptor.Singleton<IOrderService, OrderService>());
启动程序,输出如下:
获取到服务实例:DependencyInjectionDemo.Services.OrderService:53046438
因为已经注册过 OrderService,所以第二句代码不生效
以不同的实现注册服务
services.AddSingleton<IOrderService>(new OrderService()); services.TryAddEnumerable(ServiceDescriptor.Singleton<IOrderService, OrderServiceEx>());
启动程序,输出如下:
获取到服务实例:DependencyInjectionDemo.Services.OrderService:24219861 获取到服务实例:DependencyInjectionDemo.Services.OrderServiceEx:38855053
这样就可以获取到两个服务实例
刷新浏览器,再执行一遍
获取到服务实例:DependencyInjectionDemo.Services.OrderService:24219861 获取到服务实例:DependencyInjectionDemo.Services.OrderServiceEx:38855053 获取到服务实例:DependencyInjectionDemo.Services.OrderService:24219861 获取到服务实例:DependencyInjectionDemo.Services.OrderServiceEx:38855053
因为注册的是单例,所以两次请求获取到的实例都是相同的
这样做的好处是:一方面避免一个服务重复注册,也可以控制一个服务需要注册不同的实现

原文出处:微信公众号【DotNet NB】,作者【郑子铭】
原文链接:https://mp.weixin.qq.com/s/5J_Rt76xPGotROpdoFTqnw
本文观点不代表Dotnet9立场,转载请联系原作者。