当前位置: 移动技术网 > IT编程>开发语言>.net > ASP.NET Core依赖注入解读及使用Autofac替代实现

ASP.NET Core依赖注入解读及使用Autofac替代实现

2018年09月29日  | 移动技术网IT编程  | 我要评论

上海一实仪器设备厂,欧陆经典女鞋,留夏英文版

asp.net core依赖注入解读&使用autofac替代实现 1. 前言 2. asp.net core 中的di方式 3. autofac实现和自定义实现扩展方法 3.1 安装autofac 3.2 创建容器并注册依赖 

1. 前言

关于ioc模式(控制反转)和di技术(依赖注入),我们已经见过很多的探讨,这里就不再赘述了。比如说必看的martin fowler《ioc 容器和 dependency injection 模式》,相关资料链接都附于文章末尾。其中我非常赞同artech的说法"控制更多地体现为一种流程的控制",而依赖注入技术让我们的应用程序实现了松散耦合。

asp.net core本身已经集成了一个轻量级的ioc容器,开发者只需要定义好接口后,在startup.cs的configureservices方法里使用对应生命周期的绑定方法即可,常见方法如下

services.addtransient

services.addscoped

services.addsingleton

对于上述的三种di注入方式,官方也给出了详细的解释,我来简单翻译一下

transient
transient 服务在每次请求时被创建,它最好被用于轻量级无状态服务(如我们的repository和applicationservice服务) scoped
scoped 服务在每次请求时被创建,生命周期横贯整次请求 singleton
顾名思义,singleton(单例) 服务在第一次请求时被创建(或者当我们在configureservices中指定创建某一实例并运行方法),其后的每次请求将沿用已创建服务。如果开发者的应用需要单例服务情景,请设计成允许服务容器来对服务生命周期进行操作,而不是手动实现单例设计模式然后由开发者在自定义类中进行操作。

在这之后,我们便可以将服务通过构造函数注入或者是属性注入的方式注入到controller,view(通过使用@inject),甚至是filter中(以前使用unity将依赖注入到filter真是一种痛苦)。话不多说,先来体验一把

tips:startup.cs是什么,详见asp.net core 介绍和项目解读

aspnet-core-中的di方式">2. asp.net core 中的di方式

大多项目举例依赖注入的生命周期演示时,都会采取可变guid来作为返回显示,此次示例也会这样处理。我们先定义一个iguidappservice接口,里面定义基接口和三种注入模式的接口

    public interface iguidappservice
    {
        guid guiditem();
    }

    public interface iguidtransientappservice : iguidappservice
    {
    }

    public interface iguidscopedappservice : iguidappservice
    {
    }

    public interface iguidsingletonappservice : iguidappservice
    {
    }

同样的,在guidappservice中定义其实现类。这里为了直观显示每次请求的返回值,采取如下代码

    public class guidappservicebase : iguidappservice
    {
        private readonly guid _item;

        public guidappservicebase()
        {
            _item = guid.newguid();
        }

        public guid guiditem()
        {
            return _item;
        }
    }
    
    public class guidtransientappservice : guidappservicebase, iguidtransientappservice
    {
    }
    
    public class guidscopedappservice : guidappservicebase, iguidscopedappservice
    {
    }

    public class guidsingletonappservice : guidappservicebase, iguidsingletonappservice
    {
    }

最后是controller和view视图的代码

    # controller
    public class homecontroller : controller
    {
        private readonly iguidtransientappservice _guidtransientappservice; //#构造函数注入
        //private  iguidtransientappservice _guidtransientappservice { get; } #属性注入
        private readonly iguidscopedappservice _guidscopedappservice;
        private readonly iguidsingletonappservice _guidsingletonappservice;
        
        public homecontroller(iguidtransientappservice guidtransientappservice,
            iguidscopedappservice guidscopedappservice, iguidsingletonappservice guidsingletonappservice)
        {
            _guidtransientappservice = guidtransientappservice;
            _guidscopedappservice = guidscopedappservice;
            _guidsingletonappservice = guidsingletonappservice;
        }

        public iactionresult index()
        {
            viewbag.transientitem = _guidtransientappservice.guiditem();
            viewbag.scopeditem = _guidscopedappservice.guiditem();
            viewbag.singletonitem = _guidsingletonappservice.guiditem();

            return view();
        }
    }
    
    # index view 
    
    
        guiditem shows

        transientitem: @viewbag.transientitem

        scopeditem: @viewbag.scopeditem

        singletonitem: @viewbag.singletonitem
    

之后我们打开两个浏览器,分别刷新数次,也只会发现“transientitem”和“scopeditem”的数值不断变化,“singletonitem”栏的数值是不会有任何变化的,这就体现出单例模式的作用了,示例图如下

但是这好像还不够,要知道我们的scoped的解读是“生命周期横贯整次请求”,但是现在演示起来和transient好像没有什么区别(因为两个页面每次浏览器请求仍然是独立的,并不包含于一次中),所以我们采用以下代码来演示下(同一请求源)

# 新建guiditempartial.cshtml视图,复制如下代码,使用@inject注入依赖
@using dependencyinjection.iapplicationservice

@inject iguidtransientappservice transientappservice
@inject iguidscopedappservice guidscopedappservic
@inject iguidsingletonappservice guidsingletonappservice


    
        guiditem shows

        transientitem: @transientappservice.guiditem()

        scopeditem: @guidscopedappservic.guiditem()

        singletonitem: @guidsingletonappservice.guiditem()
    


# 原先的index视图
@{
    viewdata["title"] = "home page";
}

@html.partial("guiditempartial")

@html.partial("guiditempartial")

依然是 ctrl+f5 调试运行,可以发现“scopeditem”在同一请求源中是不会发生变化的,但是“transientitem”依然不断变化,理论仍然是支持的

3. autofac实现和自定义实现扩展方法

除了asp.netcore自带的ioc容器外,我们还可以使用其他成熟的di框架,如autofac,structuremap等(笔者只用过unity,ninject和castle,castle也是使用abp时自带的)。

3.1 安装autofac

首先在project.json的dependency节点中加入autofac.extensions.dependencyinjection引用,目前最新版本是4.0.0-rc3-309

3.2 创建容器并注册依赖

在startup.cs中创建一个public icontainer applicationcontainer { get; private set; }对象,并把configureservices返回类型改为iserviceprovider,然后复制以下代码进去,也可以实现相关功能

var builder = new containerbuilder();

//注意以下写法
builder.registertype().as();
builder.registertype().as().instanceperlifetimescope();
builder.registertype().as().singleinstance();

builder.populate(services);
this.applicationcontainer = builder.build();

return new autofacserviceprovider(this.applicationcontainer);

值得注意的几点:

创建autofac容器时不要忘了将configureservices的返回值修改为iserviceprovider 对应asp.net core提及的不同的生命周期,autofac也定义了对应的扩展方法,如instanceperlifetimescope等,默认为transient模式,包括entityframwork等context也是该种模式 autofac core不支持从view中注入,但是可以和asp.net core自带ioc容器配合使用 autofac core版本和传统的asp.net mvc项目版本的区别

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网