Asp.Net Core DI IoC

mac2024-05-08  37

IoC:控制反转。在一个有层级的结构中,上层依赖下层,下层的改变会影响上层。控制反转就是将自上而下的依赖链部分反转。由A->B,转变为A->Interface<-B。从中间抽象出一层来,上下2层都依赖他。只要中间这一层不变,则2端可以自由发挥。

DI:依赖注入。虽然自己依赖某个类的运行,但是自己不主动去生成某个实例,而是由调用者去生成(将依赖由自己生成变成外部注入)。自己只需要调用实例的方法即可。


模型示例

错误示范:

public class A { public void FunA() { B b = new B(); b.FunB(); } } public class B { public void FunB() { } }

评价:A中过于依赖B,B严重影响A的行为

增加DI(依赖注入)功能:

public class A { public void FunA(B b) { b.FunB(); } } public class B { public void FunB() { } }

评价:比原来好,调用时由调用者决定B的实例的生成,A中只负责使用。但是仍然有缺点,不灵活,对B接口的改变的应对方法很笨重。

将IoC和DI有机的结合:

public class A { public void FunA(Interface i) { i.Fun(); } } public interface Interface { void Fun(); } public class B : Interface { public void Fun(){} }

容器

如果我们想要调用这个A.FunA(),那么一般我们的调用步骤是实例化一个实现Interface接口的类,然后传进去,如下:

A a = new A(); a.FunA(new B());

也就是我们人为的将实例B传入Interface接口。我们也可以让程序来帮我们做到这一点。

容器的作用就是一张映射表,将一个接口和一个实现该接口的实体类绑定。没每当我们调用该接口时,则自动的创建该接口映射的实体并返回。

在.Net Core中,该容器本身由.Net来帮我们创建及维护,而我们只需要向其中添加映射关系即可。


.Net Core中的依赖注入

在.Net Core使用依赖注入步骤:

1.建立容器

2.向其中添加映射关系

3.获取依赖注入服务提供商

4.在服务提供商中确定一种映射关系

5.使用

使用示例:

//1.建立容器 var serviceCollection = new ServiceCollection() //2.添加映射关系 .AddTransient<Interface, B>(); //3.获取依赖注入服务提供商 var provider = serviceCollection.BuildServiceProvider(); //4.在服务提供商中确定一种映射关系 var b = provider.GetService<Interface>(); //5.直接使用 b.Fun(); //5.当做参数使用 A a = new A(); a.FunA(b);

在第二步中的AddTransient表示每一次请求Interface,都会生成一个B实例,这是一种映射关系。

还有其他2中映射关系:AddScope和AddSingleton。

AddScope:在一种请求范围内(scope)只会创建一个实例,哪怕多次创建这个接口。一般用于Asp.Net Core,一个Http请求算是一个Scope

AddSingleton:从项目启动后,之后只创建一次,就和单例模式一样。

var serviceCollection = new ServiceCollection() //2.添加映射关系 .AddTransient<Interface, B>() .AddScoped<Interface, C>() .AddSingleton<Interface, D>();

将一个接口映射为3个实体类,以最后一个为准

Transient,Scope,Singleton需要根据实际需求去选择。


Asp.Net Core中的依赖注入

在Startup.ConfigureServices已经定义了IServiceCollection接口。我们直接向这个接口中添加映射关系即可。

public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddTransient<Interface, B>() .AddScoped<Interface, C>() .AddScoped<Interface, D>(); }

在Controller中使用

public class ValuesController : ControllerBase { Interface _b public ValuesController(Interface B) { _b = B; } // GET api/values [HttpGet] public ActionResult<IEnumerable<string>> Get() { _b.Fun(); return new string[] { "value1", "value2" }; } }

Futher Experience

public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddTransient<B>(); services.AddTransient<Interface, B>(); services.AddTransient<Interface>(provider => new B()); services.AddTransient<Interface>(provider => new B("123")); services.AddTransient<B>(); services.AddSingleton<Interface>(new B()); services.AddSingleton<Interface>(new B("123")); services.AddSingleton(new B("123")); }

 

最新回复(0)