1. 前言

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

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

services.AddTransient<IApplicationService,ApplicationService>services.AddScoped<IApplicationService,ApplicationService>services.AddSingleton<IApplicationService,ApplicationService>

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

  • Transient
    Transient 服务在每次请求时被创建,它最好被用于轻量级无状态服务(如我们的Repository和ApplicationService服务)

  • Scoped
    Scoped 服务在每次请求时被创建,生命周期横贯整次请求

  • Singleton
    顾名思义,Singleton(单例) 服务在第一次请求时被创建(或者当我们在ConfigureServices中指定创建某一实例并运行方法),其后的每次请求将沿用已创建服务。如果开发者的应用需要单例服务情景,请设计成允许服务容器来对服务生命周期进行操作,而不是手动实现单例设计模式然后由开发者在自定义类中进行操作。

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

Tips:Startup.cs是什么,详见ASP.NET Core 介绍和项目解读

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    <div class="row">    <div >        <h2>GuidItem Shows</h2>        <h3>TransientItem: @ViewBag.TransientItem</h3>        <h3>ScopedItem: @ViewBag.ScopedItem</h3>        <h3>SingletonItem: @ViewBag.SingletonItem</h3>    </div> </div>

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

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

# 新建GuidItemPartial.cshtml视图,复制如下代码,使用@inject注入依赖
@using DependencyInjection.IApplicationService@inject IGuidTransientAppService TransientAppService
@inject IGuidScopedAppService GuidScopedAppServic
@inject IGuidSingletonAppService GuidSingletonAppService<div class="row">    <div>        <h2>GuidItem Shows</h2>        <h3>TransientItem: @TransientAppService.GuidItem()</h3>        <h3>ScopedItem: @GuidScopedAppServic.GuidItem()</h3>        <h3>SingletonItem: @GuidSingletonAppService.GuidItem()</h3>    </div></div># 原先的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<GuidTransientAppService>().As<IGuidTransientAppService>();
builder.RegisterType<GuidScopedAppService>().As<IGuidScopedAppService>().InstancePerLifetimeScope(); builder.RegisterType<GuidSingletonAppService>().As<IGuidSingletonAppService>().SingleInstance(); builder.Populate(services); this.ApplicationContainer = builder.Build();return new AutofacServiceProvider(this.ApplicationContainer);

值得注意的几点:

  1. 创建Autofac容器时不要忘了将ConfigureServices的返回值修改为IServiceProvider

  2. 对应ASP.NET Core提及的不同的生命周期,Autofac也定义了对应的扩展方法,如InstancePerLifetimeScope等,默认为Transient模式,包括EntityFramwork等Context也是该种模式

  3. Autofac Core不支持从View中注入,但是可以和ASP.NET Core自带IOC容器配合使用

  4. Autofac Core版本和传统的ASP.NET MVC项目版本的区别

4. 参考链接

  • IoC 容器和 Dependency Injection 模式

  • 控制反转—维基百科

  • DependencyInjection-GitHub

  • ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理

  • Dependency Injectionf!

原文地址:http://www.cnblogs.com/wangpd/p/7568451.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

ASP.NET Core依赖注入解读使用Autofac替代实现相关推荐

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

    1. 前言 关于IoC模式(控制反转)和DI技术(依赖注入),我们已经见过很多的探讨,这里就不再赘述了.比如说必看的Martin Fowler<IoC 容器和 Dependency Inject ...

  2. ASP.NET Core依赖注入深入讨论

    这篇文章我们来深入探讨ASP.NET Core.MVC Core中的依赖注入,我们将示范几乎所有可能的操作把依赖项注入到组件中. 依赖注入是ASP.NET Core的核心,它能让您应用程序中的组件增强 ...

  3. ASP.NET Core依赖注入最佳实践,提示技巧

    分享翻译一篇Abp框架作者(Halil İbrahim Kalkan)关于ASP.NET Core依赖注入的博文. 在本文中,我将分享我在ASP.NET Core应用程序中使用依赖注入的经验和建议. ...

  4. ASP.NET Core依赖注入容器中的动态服务注册

    介绍 在ASP.NET Core中,每当我们将服务作为依赖项注入时,都必须将此服务注册到ASP.NET Core依赖项注入容器.但是,一个接一个地注册服务不仅繁琐且耗时,而且容易出错.因此,在这里,我 ...

  5. 【ASP.NET Core】ASP.NET Core 依赖注入

    一.什么是依赖注入(Denpendency Injection) 这也是个老身常谈的问题,到底依赖注入是什么? 为什么要用它? 初学者特别容易对控制反转IOC(Iversion of Control) ...

  6. 全面理解 ASP.NET Core 依赖注入

    DI在.NET Core里面被提到了一个非常重要的位置, 这篇文章主要再给大家普及一下关于依赖注入的概念,身边有工作六七年的同事还个东西搞不清楚.另外再介绍一下.NET  Core的DI实现以及对实例 ...

  7. core控制器属性注入的用处_了解ASP.NET Core 依赖注入,看这篇就够了

    DI在.NET Core里面被提到了一个非常重要的位置, 这篇文章主要再给大家普及一下关于依赖注入的概念,身边有工作六七年的同事还个东西搞不清楚.另外再介绍一下.NET  Core的DI实现以及对实例 ...

  8. core控制器属性注入的用处_理解 ASP.NET Core 依赖注入

    DI在.NET Core里面被提到了一个非常重要的位置,介绍一下.NET  Core的DI实现以及对实例生命周期的管理,在控制台以及Mvc下如何使用DI,以及如何把默认的Service Contain ...

  9. 任务21 :了解ASP.NET Core 依赖注入,看这篇就够了

    DI在.NET Core里面被提到了一个非常重要的位置, 这篇文章主要再给大家普及一下关于依赖注入的概念,身边有工作六七年的同事还个东西搞不清楚.另外再介绍一下.NET  Core的DI实现以及对实例 ...

最新文章

  1. nginx rewrite 指令last break区别最详细的解释
  2. 注解IOC案例-把自己编写的类使用注解配置
  3. 【Workshshop No.3 | Kyligence X 青云QingCloud Workshop】零基础搭建云上大数据平台
  4. 如何让Docker镜像飞起来
  5. kafka 发布订阅_在Kafka中发布订阅模型
  6. 深入react技术栈(11):样式处理
  7. cpp知识汇总(1) 指针vs引用、static、const
  8. GitBlit使用安装教程~
  9. return 的理解
  10. linux启动java命令
  11. python 朋友圈点赞收费吗_朋友圈点赞会收费吗,人工代刷微信点赞怎么操作
  12. 支付系统中,账户体系的设计与记账处理
  13. 华为连接wifi显示wifi未连接服务器,华为路由器wifi连接上不能上网怎么办?
  14. 塞班系统更新服务器,塞班系统又更新了,又更新了,仿佛回到十年前!
  15. 【CLP】Conic Linear Programming Duality
  16. Using ‘UTF-8‘ encoding to copy filtered resources. skip non existing resourceDirectory
  17. 史上最全的Nokia3250参数
  18. 原生threeJS入门
  19. 解决“ 故障模块名称: clr.dll ”
  20. HDCTF-2nd复盘

热门文章

  1. eclipse各种配置
  2. 在web网页中正确使用图片格式
  3. C# 多个异步方法的异常处理
  4. 基于事件驱动架构构建微服务第4部分:repositories
  5. 如何禁用 ASP.NET 网站的所有的 浏览器缓存 ?
  6. ML.NET Cookbook:(20)我如何定义自己的数据转换?
  7. 我为什么对TypeScript由黑转粉?
  8. 跟我一起学.NetCore之日志(Log)模型核心
  9. WeihanLi.Npoi 1.10.0 更新日志
  10. C#高级技师语法,你会吗?