.Net Core中使用Autofac替换自带的DI容器的示例(2)

// 服务项目程序集 Assembly service = Assembly.Load("XXX.Service"); // 服务接口项目程序集 Assembly iservice = Assembly.Load("XXX.IService"); builder.RegisterAssemblyTypes(service, iservice) .Where(t => t.FullName.EndsWith("Service") && !t.IsAbstract) .InstancePerLifetimeScope() .AsImplementedInterfaces();

上面的代码就是批量注入 XXX.Service 与 XXX.IService 项目下的服务与接口。

注意:如果需要注入的服务没有 interfac ,那么builder.RegisterAssemblyTypes 就只需要传一个程序集就OK了。如果服务与接口同在一个项目,那也是要传两个程序集的哦。

然后我们在控制器去通过构造函数获取注入的实例:

private readonly IUserService userService; private readonly IProductService productService; public DefaultController(IUserService _userService, IProductService _productService) { this.userService = _userService; this.productService = _productService; }

再对之前的 Autofac 接口添油加醋:

[HttpGet] public string Autofac() { var name = userService.GetName("Autofac"); return productService.Buy(name, "批量注入"); }

结果自然是没有问题的,如果后续需要加入其它服务都不用再单独注入了,是不是优点就体现出来了。批量注入还有一些其它的玩法,比如筛选类名,筛选父类等。

.Net Core中使用Autofac替换自带的DI容器的示例

属性注入

.Net Core 自带的 DI 框架与 Autofac 默认都是构造函数注入,官方建议也是构造函数注入。

但是有些同学可能就不喜欢构造函数注入,再加上有些场景确实不适合构造函数注入(比如基类实体),所以 Autofac 也支持属性注入,下面我们来看看使用方法,在之前批量注入的基础上,我们简单改造一下:

Assembly service = Assembly.Load("Autofac.Service"); Assembly iservice = Assembly.Load("Autofac.Service"); builder.RegisterAssemblyTypes(service, iservice) .Where(t => t.FullName.EndsWith("Service") && !t.IsAbstract) .InstancePerLifetimeScope() .AsImplementedInterfaces() .PropertiesAutowired(); // 属性注入

对比构造函数注入,属性注入就多追加了PropertiesAutowired() 函数,控制器内修改:

public IUserService userService { get; set; } public IProductService productService { get; set; }

注意:属性注入记得将属性的访问修饰符改为注册类可访问的修饰符,否则会注入失败。

下面我们来看看使用效果:

.Net Core中使用Autofac替换自带的DI容器的示例

咦,怎么会空引用呢?原因大概就是 Controller 是由Mvc 模块管理的,不在 IOC 容器内,所以在 Controller 中无法使用 Autofac 注入的实例。

那为什么构造函数注入的时候又可以呢?大概或许可能他们都是构造函数注入吧...

为什么是大概呢?因为我暂时也没有具体去深入研究到底是什么原因导致的,如果有一天,我想起来去研究了并且有结果了,我会在这里补上。

我们先解决上面的问题先,在 Startup 的 ConfigureServices 方法底部加入如下代码:

// 使用 ServiceBasedControllerActivator 替换 DefaultControllerActivator; // Controller 默认是由 Mvc 模块管理的,不在 Ioc 容器中。替换之后,将放在 Ioc 容器中。 services.Replace(ServiceDescriptor.Transient<IControllerActivator, ServiceBasedControllerActivator>());

然后回到我们的AutofacModuleRegister 注入 Controller:

builder.RegisterTypes(GetAssemblyTypes<Startup>(type => typeof(ControllerBase).IsAssignableFrom(type))) .PropertiesAutowired();

这样处理完后,属性注入就Ok了。

.Net Core中使用Autofac替换自带的DI容器的示例

存储并提取容器实例

我们在之前项目的基础上添加两个项目 Common 与 Entities,存放公共类与实体类。

我们需要在实体类里面使用到 Common 项目中的某个类,结构如下:

// 基类实体   public class BaseEntity { public Class1 common_Class1 { get; set; } public string CreateId { get; set; } public void Create() { this.CreateId = common_Class1.getCurrentUserId(); } } // 公共类 public class Class1 { public string getCurrentUserId() { return Guid.NewGuid().ToString(); } }

从上面的接口中我们可以看到,我需要将 Class1 通过属性注入到容器中:

builder.RegisterType<Class1>().PropertiesAutowired().InstancePerLifetimeScope();

我们先在 Controller 中看看效果:

public Class1 class1 { get; set; } [HttpGet] public string Autofac() { return class1.getCurrentUserId(); }

很显然结果是没问题的:

.Net Core中使用Autofac替换自带的DI容器的示例

那我们再到 BaseEntity 中去试试看:

.Net Core中使用Autofac替换自带的DI容器的示例

.Net Core中使用Autofac替换自带的DI容器的示例

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyfdgz.html