依赖倒置?控制反转(IOC)? 依赖注入(DI)?

你是否还在被这些名词所困扰,是否看了大量理论文章后还是一知半解了?

今天我想结合实际项目,和正在迷惑中的新手朋友一起来学习和总结依赖注入Autofac的使用和理解。

依赖注入粗暴理解

依赖: 

public class A
{public A(B b){// do something
     }
}

这样的代码,估计没有程序猿不曾使用。

A类实例化的时候需要一个B的对象作为构造函数的参数,那么A就依赖B,这就叫依赖。

当然,不用构造函数的方式,在A类内部去new一个B,其实也是一样存在A依赖B。

注入:

看到“注入”一词,第一想到的是不是注射器?哈哈,还生活在童年阴影中。 结合一下“打针”这个场景来简单理解下依赖注入。
医生使用注射器(Autofac),将药物(依赖=类对象),注入到血管(其他类中)。

Autofac的基本使用

搭建项目

创建一个MVC项目,通过Nuget直接添加Autofac。

注入类本身.AsSelf()

    public class TestController : Controller{private readonly InjectionTestService _testService;public TestController(InjectionTestService testService){_testService = testService;}public ActionResult Index(){ViewBag.TestValue = _testService.Test();return View();}}

    public class InjectionTestService : IService{public string Test(){return "Success";}}

在Global.asax中加入依赖注入的注册代码

            // 创建一个容器var builder = new ContainerBuilder();// 注册所有的Controller
            builder.RegisterControllers(Assembly.GetExecutingAssembly());// RegisterType方式:builder.RegisterType<InjectionTestService>().AsSelf().InstancePerDependency();// Register方式:builder.Register(c => new InjectionTestService()).AsSelf().InstancePerDependency();// 自动注入的方式,不需要知道具体类的名称/* BuildManager.GetReferencedAssemblies()* 程序集的集合,包含 Web.config 文件的 assemblies 元素中指定的程序集、* 从 App_Code 目录中的自定义代码生成的程序集以及其他顶级文件夹中的程序集。*/// 获取包含继承了IService接口类的程序集var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>().Where(assembly =>assembly.GetTypes().FirstOrDefault(type => type.GetInterfaces().Contains(typeof(IService))) !=null);// RegisterAssemblyTypes 注册程序集var enumerable = assemblies as Assembly[] ?? assemblies.ToArray();if (enumerable.Any()){builder.RegisterAssemblyTypes(enumerable).Where(type => type.GetInterfaces().Contains(typeof(IService))).AsSelf().InstancePerDependency();}// 把容器装入到微软默认的依赖注入容器中var container = builder.Build();DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

为接口注入具体类.AsImplementedInterfaces()

    public class TestController : Controller{private readonly IService _testService;public TestController(IService testService){_testService = testService;}public ActionResult Index(){ViewBag.TestValue = _testService.Test();return View();}}

            // Register 方式指定具体类builder.Register(c => new InjectionTestService()).As<IService>().InstancePerDependency();// RegisterType 方式指定具体类builder.RegisterType<InjectionTestService>().As<IService>().InstancePerDependency();// 自动注册的方式// 获取包含继承了IService接口类的程序集var assemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>().Where(assembly =>assembly.GetTypes().FirstOrDefault(type => type.GetInterfaces().Contains(typeof(IService))) !=null);// RegisterAssemblyTypes 注册程序集var enumerable = assemblies as Assembly[] ?? assemblies.ToArray();if (enumerable.Any()){builder.RegisterAssemblyTypes(enumerable).Where(type => type.GetInterfaces().Contains(typeof(IService))).AsImplementedInterfaces().InstancePerDependency();}

利用Named自动注入依赖类

需求场景说明:

有A、B、C三个短信平台提供发送短信业务;

分别有三个短信平台的实现类,AMessage,BMessage,CMessage;

客户端在不同时段选取不同平台发送短信。

常规简单处理方式

新建三个服务类,AMsgService,BMsgService,CMsgService。
在客户端通过 if else 的方式判断要选用哪个短信平台,然后new服务类对象,再调用Send方法发送短信。

缺点

如果有新的短信平台D加入的话,必须新建一个DSendMsgService,然后修改客户端if else 代码。

改造

抽象一个短信平台的接口
    public interface IMessage{decimal QueryBalance();bool Send(string msg);int TotalSend(DateTime? startDate, DateTime? endDate);}

具体实现类

    [MessagePlatform(Enums.MPlatform.A平台)]public class ASendMessageService : IMessage{public decimal QueryBalance(){return 0;}public bool Send(string msg){return true;}public int TotalSend(DateTime? startDate, DateTime? endDate){return 100;}}

类有一个自定义属性标签MessagePlatform,这个是干嘛了? 是为了给这个类做一个标记,结合Named使用,实现自动注入。

    public class TestController : Controller{private Func<int, IMessage> _factory;public TestController(Func<int, IMessage> factory){_factory = factory;}public ActionResult Index(){var retult = _factory((int)Enums.MPlatform.A平台).Send("去你的吧");return View(retult);}}

构造函数参数居然是一个func的委托?

这个factory传入参数是一个int(定义好的短信平台枚举值),就可以拿到这个短信平台具体的实现类?

没错,autofac就是这么任性。

            builder.RegisterType<ASendMessageService>().Named<IMessage>((// 获取类自定义属性typeof(ASendMessageService).GetCustomAttributes(typeof(MessagePlatformAttribute), false).FirstOrDefault()as MessagePlatformAttribute).platform.ToString()).InstancePerRequest();builder.Register<Func<int, IMessage>>(c =>{var ic = c.Resolve<IComponentContext>();return name => ic.ResolveNamed<IMessage>(name.ToString());});

疑问:

上面只是给 ASendMessageService类实现了自动注入,那么BSendMessageService,CSendMessageService怎么办了,不可能都去复制一段注入的配置代码吧?

            typeof(IMessage).Assembly.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IMessage))).ForEach(type =>{// 注册type});

如果你有些实现类不在IMessge这个程序集下,那就不能这么写了,要结合具体项目情况来调整代码。

总结

1.依赖注入的目的是为了解耦。

2.不依赖于具体类,而依赖抽象类或者接口,这叫依赖倒置。

3.控制反转即IoC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。

4. 微软的DependencyResolver如何创建controller 【后续学习】

Autofac创建类的生命周期

1、InstancePerDependency

对每一个依赖或每一次调用创建一个新的唯一的实例。这也是默认的创建实例的方式。

官方文档解释:Configure the component so that every dependent component or call to Resolve() gets a new, unique instance (default.)

2、InstancePerLifetimeScope

在一个生命周期域中,每一个依赖或调用创建一个单一的共享的实例,且每一个不同的生命周期域,实例是唯一的,不共享的。

官方文档解释:Configure the component so that every dependent component or call to Resolve() within a single ILifetimeScope gets the same, shared instance. Dependent components in different lifetime scopes will get different instances.

3、InstancePerMatchingLifetimeScope

在一个做标识的生命周期域中,每一个依赖或调用创建一个单一的共享的实例。打了标识了的生命周期域中的子标识域中可以共享父级域中的实例。若在整个继承层次中没有找到打标识的生命周期域,则会抛出异常:DependencyResolutionException。

官方文档解释:Configure the component so that every dependent component or call to Resolve() within a ILifetimeScope tagged with any of the provided tags value gets the same, shared instance. Dependent components in lifetime scopes that are children of the tagged scope will share the parent's instance. If no appropriately tagged scope can be found in the hierarchy an DependencyResolutionException is thrown.

4、InstancePerOwned

在一个生命周期域中所拥有的实例创建的生命周期中,每一个依赖组件或调用Resolve()方法创建一个单一的共享的实例,并且子生命周期域共享父生命周期域中的实例。若在继承层级中没有发现合适的拥有子实例的生命周期域,则抛出异常:DependencyResolutionException。

官方文档解释:Configure the component so that every dependent component or call to Resolve() within a ILifetimeScope created by an owned instance gets the same, shared instance. Dependent components in lifetime scopes that are children of the owned instance scope will share the parent's instance. If no appropriate owned instance scope can be found in the hierarchy an DependencyResolutionException is thrown.

5、SingleInstance

每一次依赖组件或调用Resolve()方法都会得到一个相同的共享的实例。其实就是单例模式。

官方文档解释:Configure the component so that every dependent component or call to Resolve() gets the same, shared instance.

6、InstancePerHttpRequest  (新版autofac建议使用InstancePerRequest)

在一次Http请求上下文中,共享一个组件实例。仅适用于asp.net mvc开发。
官方文档解释:Share one instance of the component within the context of a single HTTP request.

 参考文档:
https://stackoverflow.com/questions/2888621/autofacs-funct-to-resolve-named-service
http://blog.csdn.net/dhx20022889/article/details/9061483

本文博客园地址:http://www.cnblogs.com/struggle999/p/6986903.html 
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。

转载于:https://www.cnblogs.com/struggle999/p/6986903.html

依赖注入之Autofac使用总结相关推荐

  1. 依赖注入容器Autofac的详解[转]

    依赖注入容器Autofac的详解 发表于 2011 年 09 月 22 日 由 renfengbin 分享到:GMAIL邮箱         Hotmail邮箱 delicious digg Auto ...

  2. 依赖注入框架Autofac学习笔记

    Autofac是一个轻量级的依赖注入框架,可以在这里面下载:http://code.google.com/p/autofac/downloads/list 要想了解什么是依赖注入,可以参考下这篇博客: ...

  3. .NET 中依赖注入组件 Autofac 的性能漫聊

    Autofac 是一款超赞的 .NET IoC 容器 ,在众多性能测评中,它也是表现最优秀的一个.它管理类之间的依赖关系, 从而使 应用在规模及复杂性增长的情况下依然可以轻易地修改.它的实现方式是将常 ...

  4. ASP.NET Core 依赖注入-集成 Autofac

    概述 ASP.NET Core 支持依赖关系注入 (DI) 软件设计模式,这是一种在类及其依赖关系之间实现控制反转 (IoC) 的技术. 默认服务容器是 Microsoft.Extensions.De ...

  5. .Net Core 3.0依赖注入替换 Autofac

    今天早上,喜庆的更新VS2019,终于3.0正式版了呀~ 有小伙伴问了一句Autofac怎么接入,因为Startup.ConfigureServices不能再把返回值改成IServiceProvide ...

  6. 【C#】依赖注入及Autofac

    文章目录 什么是依赖? 什么是注入? 为什么要反转? 何为容器 默认容器 Autofac框架 框架使用 1.NuGet引入包 2.在ConfigureServices中创建容器对象,并返回IServi ...

  7. ASP.NET Core Web 应用程序系列(三)- 在ASP.NET Core中使用Autofac替换自带DI进行构造函数和属性的批量依赖注入(MVC当中应用)...

    在上一章中主要和大家分享了在ASP.NET Core中如何使用Autofac替换自带DI进行构造函数的批量依赖注入,本章将和大家继续分享如何使之能够同时支持属性的批量依赖注入. 约定: 1.仓储层接口 ...

  8. ASP.NET Core Web 应用程序系列(二)- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)...

    在上一章中主要和大家分享在MVC当中如何使用ASP.NET Core内置的DI进行批量依赖注入,本章将继续和大家分享在ASP.NET Core中如何使用Autofac替换自带DI进行批量依赖注入. P ...

  9. dotNET Core 3.X 使用 Autofac 来增强依赖注入

    在上一篇<dotNET Core 3.X 依赖注入>中简单介绍了 dotNET Core 框架本身的依赖注入功能,大部分情况下使用框架的依赖注入功能就可以满足了,在一些特殊场景下,我们就需 ...

最新文章

  1. android WebView中js的alert()失效
  2. 金融行业创新突围,华为如何趟过产业数字化深水区?
  3. 可以发外链的网站_SEO分享:网站推广的四大推广方法
  4. 数字IC验证学习(二)
  5. 【渝粤教育】国家开放大学2018年春季 0283-21T广告创意与表现(二) 参考试题
  6. 工作338:pc重置筛选条件
  7. 【随笔】About QWERTY
  8. excel保存超过15位数据不变科学计数法的方法
  9. 张文宏:知道很多网友批评我,但粥还是不能喝
  10. Java Applet编程总结
  11. java反射优化_JAVA反射优化
  12. 基于Echarts5实现的动态排序柱状图
  13. HTML和jquery实现播放功能
  14. linux chmod 755
  15. 博图注册表删除方法_arcgis 10.2安装时error1606以及error2753解决方法记录
  16. 9、二极管的伏安特性
  17. 系统设计题面试八股文背诵版
  18. 基于蜜蜂优化算法优化的卷积神经网络(CNN)图像分类——附代码
  19. python画图--柱状图
  20. android备份:apk安装过程及原理,备份已安装应用的apk包技术实现方案

热门文章

  1. 湖南大学超级计算机中心 舒教授,湖南大学岳麓书院哲学系舒远招教授应邀来我院讲学...
  2. Intel X86 CPU系列的寄存器
  3. Spark - 大数据Big Data处理框架
  4. Microsoft Sql Server Management studio与visual studio 建立连接数据库
  5. map和struct的多重嵌套
  6. 构造函数不可以是虚函数;析构函数可以是虚函数,也可以是纯虚函数。
  7. 前端一HTML:十六: 权重有关的练习
  8. BZOJ 4584 [Apio2016]赛艇
  9. Bytomd 助记词恢复密钥体验指南
  10. POJ-1094 Sorting it All Out