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


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

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

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

    组件包

    • Microsoft.Extensions.DependencyInjection.Abstractions
    • Microsoft.Extensions.DependencyInjection

    依赖注入的核心是以上两个组件包,一个是抽象包,一个是具体的实现

    这里用到了一个经典的设计模式,接口实现分离模式

    组件只需要依赖抽象接口,而不需要依赖具体实现,当使用的时候注入它的具体实现即可

    这样做的好处是可以在使用时决定具体的实现,也就意味着未来可以做任意的扩展,替换依赖注入框架的具体实现

    默认情况下,使用 .NET Core 提供的内置依赖注入框架,也可以使用第三方的依赖注入框架来替换默认实现

    核心类型

    • IServiceCollection:服务的注册
    • ServiceDescriptor:每一个服务注册时的信息
    • IServiceProvider:具体的容器,由 ServiceCollection Build 产生
    • IServiceScope:一个容器的子容器的生命周期

    生命周期

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

    新建一个 ASP.NET Core Web 应用程序 DependencyInjectionDemo,选择API

    添加一个 Services 文件夹,新建三个服务代表三个生命周期的服务

    namespace DependencyInjectionDemo.Services
    {
        public interface IMyScopedService { }
        public class MyScopedService : IMyScopedService
        {
        }
    }
    
    namespace DependencyInjectionDemo.Services
    {
        public interface IMySingletonService { }
        public class MySingletonService : IMySingletonService
        {
        }
    }
    
    namespace DependencyInjectionDemo.Services
    {
        public interface IMyTransientService { }
        public class MyTransientService : IMyTransientService
        {
        }
    }
    

    在 Startup 中注册服务

    public void ConfigureServices(IServiceCollection services)
    {
        #region 注册服务不同生命周期的服务
    
        // 将单例的服务注册为单例的模式
        services.AddSingleton<IMySingletonService, MySingletonService>();
    
        // Scoped 的服务注册为 Scoped 的生命周期
        services.AddScoped<IMyScopedService, MyScopedService>();
    
        // 瞬时的服务注册为瞬时的生命周期
        services.AddTransient<IMyTransientService, MyTransientService>();
    
        #endregion
    
        services.AddControllers();
    }
    

    在 Controller 里面获取我们的服务

    // FromServices 标注的作用是从容器里面获取我们的对象
    // 每个对象获取两遍,用于对比每个生命周期获取的对象是什么样子的
    // HashCode 代表对象的唯一性
    [HttpGet]
    public int GetService(
        [FromServices]IMySingletonService singleton1,
        [FromServices]IMySingletonService singleton2,
        [FromServices]IMyTransientService transient1,
        [FromServices]IMyTransientService transient2,
        [FromServices]IMyScopedService scoped1,
        [FromServices]IMyScopedService scoped2)
    {
        Console.WriteLine($"singleton1:{singleton1.GetHashCode()}");
        Console.WriteLine($"singleton2:{singleton2.GetHashCode()}");
        Console.WriteLine($"transient1:{transient1.GetHashCode()}");
        Console.WriteLine($"transient2:{transient2.GetHashCode()}");
        Console.WriteLine($"scoped1:{scoped1.GetHashCode()}");
        Console.WriteLine($"scoped2:{scoped2.GetHashCode()}");
        Console.WriteLine($"========请求结束========");
        return 1;
    }
    

    启动程序,刷新浏览器再次访问接口,输出如下:

    单例模式两次的 HashCode 没有变化

    两个瞬时服务两次的 HashCode 完全不同,意味着瞬时服务每次请求都会得到一个新对象

    范围服务每个请求内是相同的,不同的请求之间得到的对象实例是不同的

    知识共享许可协议

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

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

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

  • 相关阅读:
    进程间通信 —— 命名管道
    判断当前线程是否有管理者权限
    获取操作系统OS等相关信息
    VS2017编译动态链接库报错
    git rebase 和 git merger
    Android开发之深入理解泛型extends和super的区别
    Android开发之深入理解Android Studio构建文件build.gradle配置
    Android开发之深入理解Android 7.0系统权限更改相关文档
    Android 开发之深入理解安卓调试桥各种错误解决办法
    自定义弹窗 VS AlertDialog分享弹窗
  • 原文地址:https://www.cnblogs.com/MingsonZheng/p/12324549.html
Copyright © 2020-2023  润新知