搜索

查看: 3122|回复: 11

[ASP.NET] .net程序开发IOC控制反转和DI依赖注入详解

[复制链接]
发表于 2023-5-4 11:25:35 | 显示全部楼层 |阅读模式
Editor 2023-5-4 11:25:35 3122 11 看全部
目录
  • IOC控制反转
  • DI依赖注入
  • 服务生命周期
  • 其它
    IOC控制反转
    大部分应用程序都是这样编写的:编译时依赖关系顺着运行时执行的方向流动,从而生成一个直接依赖项关系图。 也就是说,如果类 A 调用类 B 的方法,类 B 调用 C 类的方法,则在编译时,类 A 将取决于类 B,而 B 类又取决于类 C

    20221103084444037.png

    20221103084444037.png


    应用程序中的依赖关系方向应该是抽象的方向,而不是实现详细信息的方向。而这就是控制反转的思想。
    应用依赖关系反转原则后,A 可以调用 B 实现的抽象上的方法,让 A 可以在运行时调用 B,而 B 又在编译时依赖于 A 控制的接口(因此,典型的编译时依赖项发生反转)。 运行时,程序执行的流程保持不变,但接口引入意味着可以轻松插入这些接口的不同实现。

    20221103084444038.png

    20221103084444038.png


    上下不同的实现方式在于之前的依赖关系是A->B->C,控制反转后A->B接口->C接口,然后具体的B,C实现又是B->B接口 的反转依赖。这样的好处就是A只依赖B接口而不是依赖实现,具体我们要实现什么只需要按照业务需求进行编写,并且可以随时替换实现而不会影响A的实现,这种思想就是控制反转。
    如下是顺序依赖:
            public class A
            {
                //依赖具体类
                public B b;
                public C c;
                public A(B _b, C _c) {
                    b = _b;
                    c = _c;
                }
                public void Listen()
                {
                    b.SayHi();
                    c.SayBye();
                }
            }
            public class B
            {
                public void SayHi()
                {
                    Console.WriteLine("hi...");
                }
            }
            public class C
            {
                public void SayBye()
                {
                    Console.WriteLine("bye...");
                }
            }
    如下是控制反转:
            public class A
            {
                //依赖接口
                public IB b;
                public IC c;
                public A(IB _b, IC _c)
                {
                    b = _b;
                    c = _c;
                }
                public void Listen()
                {
                    b.SayHi();
                    c.SayBye();
                }
            }
            public interface IB
            {
                public void SayHi();
            }
            public interface IC
            {
                public void SayBye();
            }

    DI依赖注入
    .NET 支持依赖关系注入 (DI) 软件设计模式,这是一种在类及其依赖项之间实现控制反转 (IoC) 的技术。
    我们首先用代码来看什么是DI,在.net提供的扩展包Microsoft.Extensions.DependencyInjection中来完成DI,nuget安装。

    20221103084444039.png

    20221103084444039.png


    然后我们实现接口B和接口C,实现我们可以说英语,也可以说汉语,我们在SayHi和SayBye中输出汉语。
            public class B : IB
            {
                public void SayHi()
                {
                    Console.WriteLine("你好...");
                }
            }
            public class C : IC
            {
                public void SayBye()
                {
                    Console.WriteLine("再见...");
                }
            }
    然后在服务容器中注册依赖关系。 .NET 提供了一个内置的服务容器 IServiceProvider。 服务通常在应用启动时注册,并追加到 IServiceCollection。 添加所有服务后,可以使用 BuildServiceProvider 创建服务容器,然后在容器中直接“要”对象而不用去管它如何实例化,并且DI具备传染性,假如B引用了D接口ID,那么我们注册B并在获取B实例时,引用的D接口也会被实例化。
                //IServiceCollection 服务
                IServiceCollection services = new ServiceCollection();
                //服务注册
                services.AddTransient();
                services.AddTransient[I]();
                services.AddTransient[I]();
                //创建服务容器
                var serviceProvider = services.BuildServiceProvider();
                //获取服务
                var a = serviceProvider.GetRequiredService();
                //使用
                a.Listen();
                Console.ReadKey();

    20221103084444040.png

    20221103084444040.png


    这就是通过DI依赖注入的方式来实现IOC的思想,或许你会好奇为什么我们不直接实例化A,然后在构造方法里面传进去就行了,也就不依赖DI实现了。但是程序结构更复杂些呢,比如上面提到的B又有D,D又有F呢,这样在构造的时候不是一直要new很多对象,而且同一个接口的不同实现还要去找实例化处的代码进行修改。例如SayHI我想说英文呢?那么我们就可以实现一个BB,然后在服务注册的地方注册BB就可以了。
            public class BB : IB
            {
                public void SayHi()
                {
                    Console.WriteLine("hello...");
                }
            }
    替换注册BB services.AddTransient[I](),而不用去改任何逻辑。

    20221103084444041.png

    20221103084444041.png


    服务生命周期
    在注册服务的时候我使用的AddTransient方法,表示注册的服务是瞬态的,也就是每次请求都是重新创建实例。同时还提供其它注册服务的方法。

    20221103084444042.png

    20221103084444042.png


    服务有三种声明周期:
    瞬态
    作用域
    单例
  • 瞬态
    服务是每次从服务容器进行请求时创建的。 这种生存期适合轻量级、 无状态的服务。 用 AddTransient 注册服务。在处理请求的应用中,在请求结束时会释放暂时服务。
  • 作用域
    指定了作用域的生存期指明了每个客户端请求(连接)创建一次服务。 向 AddScoped 注册范围内服务。在处理请求的应用中,在请求结束时会释放有作用域的服务。
    想asp.net 在处理一个请求的时候是一个作用域,同样我们自己也可以定义作用域。使用serviceProvider.CreateScope()创建作用域,在作用域释放后对象将被释放。

    20221103084444043.png

    20221103084444043.png


    我们使用AddScoped添加对象,然后在作用域中取两个A对象进行比较,可以看到是True。
    如果我们用AddTransient注册A,即使在作用域内两个对象比较也是不一样的,结果为False。

    20221103084444044.png

    20221103084444044.png


  • 单例
    单例大家应该好理解,就是设计模式中的单例,使用AddSingleton 注册,在首次请求它们时进行创建;或者在向容器直接提供实现实例时由开发人员进行创建。 很少用到此方法,因为可能是线程不安全的,如果服务中有状态。

    其它
    在Microsoft.Extensions.DependencyInjection中只能用构造函数注入,其它框架还提供属性注入,比如autofac。至于原因不得而知,当然也看个人喜好。查了些资料说是构造函数注入更科学,在对象创建的瞬间对象的构造方法将服务实例化,避免逻辑问题。
    以上就是.net程序开发IOC控制反转和DI依赖注入详解的详细内容,更多关于.net 控制反转依赖注入的资料请关注知鸟论坛其它相关文章!
  • 回复

    使用道具 举报

    发表于 2023-6-29 01:23:34 | 显示全部楼层
    落败的青春阳落s 2023-6-29 01:23:34 看全部
    既然你诚信诚意的推荐了,那我就勉为其难的看看吧!知鸟论坛不走平凡路。
    回复

    使用道具 举报

    发表于 2023-6-29 16:57:08 | 显示全部楼层
    米老鼠和蓝精鼠v 2023-6-29 16:57:08 看全部
    楼主,大恩不言谢了!知鸟论坛是最棒的!
    回复

    使用道具 举报

    发表于 2023-6-30 16:29:58 | 显示全部楼层
    123456868 2023-6-30 16:29:58 看全部
    论坛不能没有像楼主这样的人才啊!我会一直支持知鸟论坛
    回复

    使用道具 举报

    发表于 2023-7-4 01:04:52 | 显示全部楼层
    丁侦球 2023-7-4 01:04:52 看全部
    论坛不能没有像楼主这样的人才啊!我会一直支持知鸟论坛
    回复

    使用道具 举报

    发表于 2023-7-6 04:35:47 | 显示全部楼层
    贺老师 2023-7-6 04:35:47 看全部
    楼主,大恩不言谢了!知鸟论坛是最棒的!
    回复

    使用道具 举报

    发表于 2023-7-6 05:29:26 | 显示全部楼层
    胡37 2023-7-6 05:29:26 看全部
    我看不错噢 谢谢楼主!知鸟论坛越来越好!
    回复

    使用道具 举报

    发表于 2023-7-6 09:32:59 | 显示全部楼层
    普通人物怨 2023-7-6 09:32:59 看全部
    论坛不能没有像楼主这样的人才啊!我会一直支持知鸟论坛
    回复

    使用道具 举报

    发表于 2023-7-6 20:24:20 | 显示全部楼层
    塞翁364 2023-7-6 20:24:20 看全部
    这东西我收了!谢谢楼主!知鸟论坛真好!
    回复

    使用道具 举报

    发表于 2023-7-6 20:25:13 | 显示全部楼层
    啤酒瓶空了缓 2023-7-6 20:25:13 看全部
    这个帖子不回对不起自己!我想我是一天也不能离开知鸟论坛
    回复

    使用道具 举报

    • 您可能感兴趣
    点击右侧快捷回复 【请勿灌水】
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则 返回列表

    RSS订阅| SiteMap| 小黑屋| 知鸟论坛
    联系邮箱E-mail:zniao@foxmail.com
    快速回复 返回顶部 返回列表