美文网首页.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