当前位置: 代码网 > it编程>编程语言>Asp.net > .net程序开发IOC控制反转和DI依赖注入详解

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

2024年05月19日 Asp.net 我要评论
ioc控制反转大部分应用程序都是这样编写的:编译时依赖关系顺着运行时执行的方向流动,从而生成一个直接依赖项关系图。 也就是说,如果类 a 调用类 b 的方法,类 b 调用 c 类的方法,则在编译时,类

ioc控制反转

大部分应用程序都是这样编写的:编译时依赖关系顺着运行时执行的方向流动,从而生成一个直接依赖项关系图。 也就是说,如果类 a 调用类 b 的方法,类 b 调用 c 类的方法,则在编译时,类 a 将取决于类 b,而 b 类又取决于类 c

应用程序中的依赖关系方向应该是抽象的方向,而不是实现详细信息的方向。而这就是控制反转的思想。

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

上下不同的实现方式在于之前的依赖关系是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安装。

然后我们实现接口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<a>();
            services.addtransient<ib, b>();
            services.addtransient<ic, c>();
            //创建服务容器
            var serviceprovider = services.buildserviceprovider();
            //获取服务
            var a = serviceprovider.getrequiredservice<a>();
            //使用
            a.listen();
            console.readkey();

这就是通过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<ib, bb>(),而不用去改任何逻辑。

服务生命周期

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

服务有三种声明周期:

瞬态

作用域

单例

  • 瞬态

服务是每次从服务容器进行请求时创建的。 这种生存期适合轻量级、 无状态的服务。 用 addtransient 注册服务。在处理请求的应用中,在请求结束时会释放暂时服务。

  • 作用域

指定了作用域的生存期指明了每个客户端请求(连接)创建一次服务。 向 addscoped 注册范围内服务。在处理请求的应用中,在请求结束时会释放有作用域的服务。

想asp.net 在处理一个请求的时候是一个作用域,同样我们自己也可以定义作用域。使用serviceprovider.createscope()创建作用域,在作用域释放后对象将被释放。

我们使用addscoped添加对象,然后在作用域中取两个a对象进行比较,可以看到是true

如果我们用addtransient注册a,即使在作用域内两个对象比较也是不一样的,结果为false

  • 单例

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

其它

在microsoft.extensions.dependencyinjection中只能用构造函数注入,其它框架还提供属性注入,比如autofac。至于原因不得而知,当然也看个人喜好。查了些资料说是构造函数注入更科学,在对象创建的瞬间对象的构造方法将服务实例化,避免逻辑问题。

以上就是.net程序开发ioc控制反转和di依赖注入详解的详细内容,更多关于.net 控制反转依赖注入的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com