zoukankan      html  css  js  c++  java
  • .NET Core开发实战(第5课:依赖注入:良好架构的起点)--学习笔记(中)

    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
    

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

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

    知识共享许可协议

    本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

    欢迎转载、使用、重新发布,但务必保留文章署名 郑子铭 (包含链接: http://www.cnblogs.com/MingsonZheng/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。

    如有任何疑问,请与我联系 (MingsonZheng@outlook.com) 。

  • 相关阅读:
    从上往下打印二叉树
    栈的压入、弹出序列
    连续子数组的最大和
    链表中环形的入口
    1月项目痛点
    problem:vue组件局部刷新,在组件销毁(destroyed)时取消刷新无效问题
    重点:浏览器的工作原理
    12月中旬项目中出现的几个bug解决方法的思考
    12月中项目问题复盘之对项目进度把控的反思
    problem: vue之数组元素中的数组类型值数据改变却无法在子组件视图更新问题
  • 原文地址:https://www.cnblogs.com/MingsonZheng/p/12329444.html
Copyright © 2011-2022 走看看