美文网首页.Net Core
NETCore下DI使用总结

NETCore下DI使用总结

作者: voxer | 来源:发表于2018-08-13 18:35 被阅读264次

上文,我们来看看NETCore下DI的使用。我们这里其实主要是讨论ASP.NETCore,因为我们最主要是用NETCore来实现WebAPI。

1. 注册和获取服务

ASP.NETCore框架核心就是依赖注入,它的服务容器就是IServiceCollection,大家可以理解为一个服务注册的字典,Key是接口,Value是注册到这个接口上的接口实现,重复注册是会覆盖前一次的注册。
大家可以单步跟踪一下IServiceCollection的值,可以看到执行AddMvc之前里面有63个值,执行AddMvc后就变成200多个,说明AddMvc是相当于执行了100多次服务的注入。我们如果自己要注入一个服务的话,类似以下代码:

services.AddSingleton<Interface1, Class1>();
services.AddTransient<Interface2, Class2>();
services.AddScoped<Interface3, Class3>();

服务注册之后,如何根据接口来获取实例了,通常二种方式:
第一种:通过IServiceProvider接口或通过IServiceCollection来获取ServiceProvider实例

var provider = services.BuildServiceProvider();
var class1 = provider.GetService<Interface1>();
 Console.WriteLine(class1.function1());
public ValuesController(IServiceProvider provider)
{
    Console.WriteLine(i1.function1());
    Console.WriteLine(i2.function2());
    Console.WriteLine(i3.function3());
    var test = provider.GetService<TestScopeClass>();
}

第二种:直接在构造函数里把接口作为参数

public ValuesController(Interface1 i1, Interface2 i2, Interface3 i3)
 {
      Console.WriteLine(i1.function1());
      Console.WriteLine(i2.function2());
      Console.WriteLine(i3.function3());
 }

2. 生命周期

每个注入的实例都是有生命周期的,生命周期就三种

  1. AddSingleton : 在整个应用生命周期里都是唯一
  2. AddTransient:每次获取一次服务就创建一个实例
  3. AddScoped:在我们自定义的Scope内的生命周期,在Scope内是唯一

前二种比较简单,Scope的说一下,参考例子:

using (var scope1 = provider.CreateScope())
{
    var p = scope1.ServiceProvider;

    var scopeobj1 = p.GetService<Interface3>();
    var transient1 = p.GetService<Interface2>();
    var singleton1 = p.GetService<Interface1>();

    var scopeobj2 = p.GetService<Interface3>();
    var transient2 = p.GetService<Interface2>();
    var singleton2 = p.GetService<Interface1>();

    Console.WriteLine(
        $"scope1: { scopeobj1.function3() }," +
        $"transient1: {transient1.function2()}, " +
        $"singleton1: {singleton1.function1()}");

    Console.WriteLine($"scope2: { scopeobj2.function3() }, " +
        $"transient2: {transient2.function2()}, " +
        $"singleton2: {singleton2.function1()}");
}

运行这个函数二遍,我们看结果,可以看出在不同的Scope下对象不一样,但是在一个Scope下获取二次对象是一样的。


image.png

这个例子不是那么直观,在ASP.NETCore下最常用的其实是Http的请求处理,每次请求都会创建一个新的Scope里,这样的话,这个请求内所有scope的注入对象都只有一份,比如DbContext对象在一次请求里是不会变的,这样确保一次请求对数据库的操作不会错乱。但是多次请求就不一样了。我们看看另外一个例子,在controller里的例子:

public class ValuesController : Controller
{
    public ValuesController(Interface1 i1, Interface2 i2, Interface3 i3,IServiceProvider provider)
    {
        Console.WriteLine(i1.function1());
        Console.WriteLine(i2.function2());
        Console.WriteLine(i3.function3());
        var test = provider.GetService<Interface3>();
        Console.WriteLine(test.function3());
    }

再看看执行的结果:


image.png

可以看出http请求了二次,每次Class3的对象都不一样,但是在一个请求里多次获取对象是一样的。

示例代码参考Github

相关文章

网友评论

    本文标题:NETCore下DI使用总结

    本文链接:https://www.haomeiwen.com/subject/rpwcvftx.html