zoukankan      html  css  js  c++  java
  • .NET Core-依赖注入:良好架构的起点

    .NET Core使用依赖注入框架来管理服务的依赖与生命周期。

    Table of Contents

    为何需要依赖注入框架?

    依赖注入的组件包

    核心类型

    生命周期

    服务的注册方式

    正常注册

    花式注册(包含实例注入、工厂模式)

    尝试注册

    替换和移除

    泛型注册

    获取依赖注入实例的2种方式

    构造函数注入

    为何需要依赖注入框架?
    借助依赖注入框架,可轻松管理类之间的依赖,便于遵循设计原则,确保代码的可维护性和可扩展性
    ASP.NET Core的整个架构中,依赖注入框架提供了对象创建和生命周期管理的核心能力,各个组件相互协作,也是由依赖注入框架的能力来实现的。
    依赖注入的组件包
    包括2个,一个是抽象包,一个是具体实现包,符合接口实现分离原则,便于调用

    Microsoft.Extensions.DependencyInjection.Abstractions
    Microsoft.Extensions.DependencyInjection
    核心类型
    依赖注入框架包括以下的4个核心类型,并负责不同的分工

    类型 内容
    IServiceCollection 负责服务的注册
    IServiceDescriptor 服务注册信息描述
    IServiceProvider 具体的容器,由IServiceCollection创建
    IServiceScope 表示容器的子容器的生命周期
     

    生命周期
    生命周期有3种,分别为Singleton、Scoped、Transient

    Singleton 整个根容器内都是单例
    Scoped 在当前容器的生命周期内是单例的
    Transient 每次获取对象都是全新对象
    服务的注册方式
    在容器内注册服务可以有以下几种注册方式

    正常注册
    services.AddSingleton<IMySingletonService, MySingletonService>();
    services.AddScoped<IMyScopedService, MyScopedService>();
    services.AddTransient<IMYTransientService, MyTransientService>();
    花式注册(包含实例注入、工厂模式)
    //直接注入实例
    services.AddSingleton<IOrderService>(new OrderService());
    //工厂注册
    services.AddSingleton<IOrderService>(factory =>
    {
    return new OrderServiceEx();
    });//可以注入,实现不同
    尝试注册
    尝试注册分为2种,一种是TryAdd...形式,一种是TryAddEnumerable形式,区别是

    TryAdd...形式只能注册同一类型的一个服务,即使实现不同也不能注入

    TryAddEnumerable可注册相同类型的不同实现

    //TryAdd...,相同类型的不会重复注入
    services.TryAddSingleton<IOrderService, OrderService>();//不会注入,相同类型的都不会注入
    services.TryAddSingleton<IOrderService, OrderServiceEx>();//不会注入,相同类型的都不会注入
    //TryAddIEnumerable,可以注入不同实现
    //services.TryAddEnumerable(services.AddSingleton<IOrderService, OrderService>());//注入报错,System.ArgumentException
    services.TryAddEnumerable(ServiceDescriptor.Singleton<IOrderService, OrderServiceEx>());//可以注入
    //注入报错,System.ArgumentException
    //services.TryAddEnumerable(ServiceDescriptor.Singleton<IOrderService>(factory =>
    //{
    // return new OrderServiceEx();
    //}));
    由以上代码,我们可以看出,尝试注入相同的实现,会抛System.ArgumentException异常。

    替换和移除
    出去服务的注册,我们还需要了解服务的替换和移除方式,服务的替换有助于我们抛弃他人的定义来使用自己的定义

    services.Replace(ServiceDescriptor.Singleton<IOrderService, OrderServiceEx>());//经测试,这里只能替换非尝试注册的服务
    services.Remove(ServiceDescriptor.Singleton<IOrderService, OrderService>());
    //services.RemoveAt(0);
    //services.RemoveAll<IOrderService>();
    这里,我经过代码测试,发现,服务替换只能替换非尝试注册的方式,而尝试注册的方式不受影响,这里要注意一下,虽然还不知道原理是什么。这里是错误结论,replace方法是移除第一个同类型的服务,并添加当前的服务,而不是全部替换。

    泛型注册
    其实,不管是什么类型,注册方式都是类似的,常规注入方式需要提供2个类型,分别是接口定义和接口实现,那么一个泛型类型的定义可如下

    services.AddSingleton(typeof(IGenericServie<>),typeof(GenericService<>));
    获取依赖注入实例的2种方式
    获取依赖注入实例有2种方式,且对应于不同的使用场景

    构造函数注入 适用于controller中大部分服务都需要用到的情况
    [FromService]标签
    适用于服务仅有某个接口使用的情况

    [FromService]可从容器中获取服务对象。

    示例如下:

    构造函数注入

    public WeatherForecastController(ILogger<WeatherForecastController> logger,IOrderService orderService,IGenericServie<IOrderService> genericServie)
    {
    _logger = logger;
    }
    [FromService]获取

    [HttpGet]
    public int GetServiceList([FromServices] IEnumerable<IOrderService> orderServices)
    {
    foreach (var item in orderServices)
    {
    Console.WriteLine($"{item.GetType()}-{item.GetHashCode()}");
    }
    return 1;
    }
     

    到这里,本节就要结束了,下一节学习作用于与对象的释放行为。

    源码可访问

    https://github.com/IronMarmot/Samples/tree/master/CoreSamples
    ————————————————
    版权声明:本文为CSDN博主「攻城狮客栈」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/xiansenLee/article/details/105887089

  • 相关阅读:
    透明PNG格式图片兼容IE6浏览器
    CSS英文单词强制换行
    未能加载文件或程序集“Oracle.DataAccess, Version=2.111.7.0, Culture=neutral, PublicKeyToken=89b483f429c47342”或它的某一个依赖项。试图加载格式不正确的程序
    使用IIS 无法命中Application_Start中的断点问题
    win7 x64 后蓝牙u盘搜索不到其他设备
    使用Html.BeginForm<T>后客户端脚本验证出错的问题
    为什么使用sealed修饰符
    vs2010调试时发生监视显示表达式为false,但却进入了if块中
    MicrosoftMvcJQueryValidation.js 启用客户端验证,form无法提交
    Jquery 操作页面中iframe自动跟随窗口大小变化,而不出现滚动条,只在iframe内部出滚动条
  • 原文地址:https://www.cnblogs.com/cxxtreasure/p/14586003.html
Copyright © 2011-2022 走看看