.net程序开发IOC控制反转和DI依赖注入详解
发布时间:2023-02-17 10:01:26 所属栏目:asp.Net 来源:互联网
导读:IOC控制反转 大部分应用程序都是这样编写的:编译时依赖关系顺着运行时执行的方向流动,从而生成一个直接依赖项关系图。 也就是说,如果类 A 调用类 B 的方法,类 B 调用 C 类的方法,则在编译时,类 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()创建作用域,在作用域释放后对象将被释放。 (编辑:莱芜站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- asp.net – 无法加载文件或程序集App_Licenses
- asp.net-mvc-3 – DropDownListFor Unobtrusive Validation
- ASP.NET和System.Diagnostics跟踪 – 我错过了什么,或者这是
- asp.net-mvc-3 – Telerik MVC网格,在运行时从集合或字典中
- asp.net-mvc – 使用ASP.Net MVC中的模型绑定器更新父/子记
- .net – RESTful WCF的裸最低配置
- 将ASP.NET身份与核心域模型分离 – 洋葱架构
- asp.net-mvc – 如何从mvc中的控制器中设置隐藏字段的值
- asp.net-mvc – asp.net MVC antiorgerytoken异常RedirectT
- asp.net-mvc-3 – ASP.net MVC – 模型绑定不包括类字段?
推荐文章
站长推荐
- asp.net – ASP MVC用户配置文件
- ASP.NET虚拟路径映射到另一个不允许的应用程序
- asp.net – Oracle.ManagedDataAccess:TNS:无法
- asp.net-mvc – 在asp.net mvc中设置为Session的
- asp.net-mvc – View中的意外NullReferenceExcep
- asp.net – Orchard CMS是否支持移动呈现?
- 如何通过ASP.NET中的另一个下拉列表过滤下拉列表
- asp.net – 多个用户控件和JavaScript
- asp.net-mvc – 删除布局将默认为_ViewStart,为什
- .net – 可以为空的枚举类型的奇怪行为
热点阅读