使用 autofac 代替 asp .net core 默认的 IOC 容器,可实现属性注入。

之前的使用方式不受影响。

源码已开源:

dotnet-campus/Autofac.Annotation: Autofac 扩展,使用 Attribute 进行服务注册与属性注入

更丰富的功能,可以看这里:

yuzd/Autofac.Annotation: Autofac extras library for component registration via attributes 用注解来load autofac 摆脱代码或者xml配置和java的spring的注解注入一样的体验

使用效果示例

向容器中注入服务

builder.RegisterType<Counter>().As<ICounter>().InstancePerDependency().AsImplementedInterfaces();

通过属性获取服务

[Autowired]  // 这个不是 autofac 自带的,是自己实现的,可以不要。见后面的详述。
private ICounter Counter { get; set; }

准备工作

  • nuget 引用
    <PackageReference Include="Autofac" Version="5.2.0" />
<PackageReference Include="Autofac.Extensions.DependencyInjection" Version="6.0.0" />
  • Program.cs 文件

使用autofac的容器工厂替换系统默认的容器

  • Startup.cs 文件

在 Startup 服务配置中加入控制器替换规则

services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());

这句的意思:使用 ServiceBasedControllerActivator 替换 DefaultControllerActivator;Controller 默认是由 Mvc 模块管理的,不在 Ioc 容器中。替换之后,将放在 Ioc 容器中。

在 Startup.cs 添加 public void ConfigureContainer(ContainerBuilder builder) 方法,这个方法会由 autofac 自动调用。

在这个方法中,进行依赖的注入和属性注入的配置。

        // ConfigureContainer is where you can register things directly
// with Autofac. This runs after ConfigureServices so the things
// here will override registrations made in ConfigureServices.
// Don't build the container; that gets done for you by the factory.
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterModule<BaseServiceRegisterModule>();
builder.RegisterModule<PropertiesAutowiredModule>();
}

在 autofac 中,有一个 Module 的概念,可以分模块处理依赖的注入。试想,如果所有业务相关的依赖注入代码,都放在 Startup.cs 这一个文件中,代码会变得很难看。

这里的示例中,定义了 BaseServiceRegisterModulePropertiesAutowiredModule ,分别写服务注入的代码,和属性注入的配置代码。

具体实现

下面把后面要说明的四个类都列出来:

    public class BaseServiceRegisterModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
// Register your own things directly with Autofac, like:
builder.RegisterType<Counter>().As<ICounter>().InstancePerDependency().AsImplementedInterfaces();
}
}
    public class PropertiesAutowiredModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
// 获取所有控制器类型并使用属性注入
var controllerBaseType = typeof(ControllerBase);
builder.RegisterAssemblyTypes(typeof(Program).Assembly)
.Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
.PropertiesAutowired(new AutowiredPropertySelector());
}
}
    public class AutowiredPropertySelector: IPropertySelector
{
public bool InjectProperty(PropertyInfo propertyInfo, object instance)
{
return propertyInfo.CustomAttributes.Any(it => it.AttributeType == typeof(AutowiredAttribute));
}
} [AttributeUsage(AttributeTargets.Property)]
public class AutowiredAttribute : Attribute
{
}

BaseServiceRegisterModule 中,向容器中注入了 ICounter 这个服务。

PropertiesAutowiredModule 中,配置了属性注入的操作。这里是关键了。

            var controllerBaseType = typeof(ControllerBase);
builder.RegisterAssemblyTypes(typeof(Program).Assembly)
.Where(t => controllerBaseType.IsAssignableFrom(t) && t != controllerBaseType)
.PropertiesAutowired(new AutowiredPropertySelector());

代码还是挺直白的,需要说明

1 可以看到,属性注入并不是 autofac 自动 帮我们完成的,得自己写代码,使用反射的方式,给哪些类进行属性注入。

2 在上面的代码中,只给 ControllerBase 的子类进行了属性注入。

3 这里在 PropertiesAutowired 方法中,加了一个自定义的 AutowiredPropertySelector

如果没有给 PropertiesAutowired 添加任何方法参数,则 autofac 会对所有属性尝试进行注入,PropertiesAutowired 的方法参数,可以指定属性选择器。

在本文的示例中,选择器的实现是:

        public bool InjectProperty(PropertyInfo propertyInfo, object instance)
{
return propertyInfo.CustomAttributes.Any(it => it.AttributeType == typeof(AutowiredAttribute));
}

也就是要求属性必须显式的标明 [Autowired] 这个 Attribute。

我这里这样做的目的是为了让代码看起来更直观,哪些属性是自动注入的,哪些不是,一目了然。

最终效果

在依赖注册上(向容器中添加服务),并没有变化,还是需要手工写代码(在 Startup.cs 或者 Module 中),当然,也可以利用反射,自定义一个 Attribute,然后写一端代码自动将其注入到容器中。

在依赖注入上(从容器中获取服务),这里可以利用属性进行“自动”注入了。使用起来就是这样 ↓,比 asp.net core 中只能是构造函数注入,方便了很多。

        [Autowired]
private ICounter Counter { get; set; }

尾巴

对比 spring 框架,asp.net core 的 IOC 在易用性上,感觉还是弱了不少。不过看到这篇博客:ASP.NET Core 奇淫技巧之伪属性注入 - 晓晨Master - 博客园

觉得属性注入不可滥用的说法还是有道理的,会造成依赖关系的隐藏。

参考文章

主要参考文章:

ASP.NETCore 3.0 Autofac替换及控制器属性注入及全局容器使用 - 情·深 - 博客园

autofac 的官方示例:

autofac/Examples: Example projects that consume and demonstrate Autofac IoC functionality and integration

autofac 文档:

Welcome to Autofac’s documentation! — Autofac 5.2.0 documentation

欢迎来到 Autofac 中文文档! — Autofac 4.0 文档

其它:

ASP.NET Core 奇淫技巧之伪属性注入 - 晓晨Master - 博客园

.net core2.0下Ioc容器Autofac使用 - 焰尾迭 - 博客园

原文链接:

https://www.cnblogs.com/jasongrass/p/13457212.html

使用 autofac 实现 asp .net core 的属性注入的更多相关文章

  1. Hangfire&Autofac与ASP.NET CORE注入失败

    Hangfire.Autofac与ASP.NET CORE注入失败 项目里面使用了Hangfire,因为之前没用过吧,遇到了个问题,就是使用了ico容器后,再用Hangfire总是注入不上对象,总是后 ...

  2. ASP.NET Core之依赖注入

    本文翻译自:http://www.tutorialsteacher.com/core/dependency-injection-in-aspnet-core ASP.NET Core支持依赖注入,依赖 ...

  3. 几十行代码实现ASP.NET Core自动依赖注入

    在开发.NET Core web服务的时候,我们习惯使用自带的依赖注入容器来进行注入. 于是就会经常进行一个很频繁的的重复动作:定义一个接口->写实现类->注入 有时候会忘了写Add这一步 ...

  4. Asp.Net MVC 之 Autofac 初步使用2 集成mvc 属性注入以及自动注入

    首先看下Demo2的结构     然后下面一步步将Autofac集成到mvc中. 首先,定义Model Product.cs public class Product { public int Id ...

  5. Asp.net core自定义依赖注入容器,替换自带容器

    依赖注入 在asp.net core程序中,众所周知,依赖注入基本上贯穿了整个项目,以通用的结构来讲解,控制器层(Controller层)依赖业务层(Service层),业务层依赖于仓储层(Repos ...

  6. 【ASP.NET Core】依赖注入高级玩法——如何注入多个服务实现类

    依赖注入在 ASP.NET Core 中起中很重要的作用,也是一种高大上的编程思想,它的总体原则就是:俺要啥,你就给俺送啥过来.服务类型的实例转由容器自动管理,无需我们在代码中显式处理. 因此,有了依 ...

  7. asp.net core 系列 4 注入服务的生存期

    一.服务的生存期 在容器中每个注册的服务,根据程序应用需求都可以选择合适的服务生存期,ASP.NET Core 服务有三种生存期配置: (1) Transient:暂时生存期,在每次请求时被创建. 这 ...

  8. asp.net core ioc 依赖注入

    1.生命周期 内置的IOC有三种生命周期: Transient: Transient服务在每次被请求时都会被创建.这种生命周期比较适用于轻量级的无状态服务. Scoped: Scoped生命周期的服务 ...

  9. (2)ASP.NET Core 依赖关系注入(服务)

    1.前言 面向对象设计(OOD)里有一个重要的思想就是依赖倒置原则(DIP),并由该原则牵引出依赖注入(DI).控制反转(IOC)及其容器等老生常谈的概念,初学者很容易被这些概念搞晕(包括我在内),在 ...

随机推荐

  1. Java中集合的有序问题

    Java中的容器主要包括两方面: Collection:List.Set.queue Map:HashMap.treeMap: 一. Collection 1. Set TreeSet:基于红黑树实现 ...

  2. 多线程(二)多线程的基本原理+Synchronized

    由一个问题引发的思考 线程的合理使用能够提升程序的处理性能,主要有两个方面, 第一个是能够利用多核 cpu 以及超线程技术来实现线程的并行执行: 第二个是线程的异步化执行相比于同步执行来说,异步执行能 ...

  3. Linux内核实现透视---软中断&Tasklet

    软中断 首先明确一个概念软中断(不是软件中断int n).总来来说软中断就是内核在启动时为每一个内核创建了一个特殊的进程,这个进程会不停的poll检查是否有软中断需要执行,如果需要执行则调用注册的接口 ...

  4. 智能广告投放平台 All in One

    智能广告投放平台 All in One app demos 知之数据 一站式广告营销平台 https://hio.cn/ refs https://www.jonmellman.com/posts/p ...

  5. hihoCoder Challenge 2

    #1046 : K个串 时间限制:40000ms 单点时限:2000ms 内存限制:1024MB 描述 兔子们在玩k个串的游戏.首先,它们拿出了一个长度为n的数字序列,选出其中的一个连续子串,然后统计 ...

  6. 使用 js 实现一个简易版的模版引擎

    使用 js 实现一个简易版的模版引擎 regex (function test() { this.str = str; })( window.Test = ...; format() { let ar ...

  7. PDF transform to PPT online & free

    PDF transform to PPT online & free > Speaker Deck Share Presentationswithout the Mess Speaker ...

  8. prefetch & preload & prerender & dns-prefetch & preconnect

    prefetch & preload & prerender & dns-prefetch & preconnect performance optimization ...

  9. UX & feedback & instant visual feedback

    UX & feedback & instant visual feedback Select an element on the page https://ant.design/com ...

  10. 口罩 & 防毒面具 N95 & P100

    口罩 & 防毒面具 N95 & P100 N95 口罩 < 防毒面具 P100 https://www.techritual.com/2020/01/30/210599/