ASP.NET Core MVC依赖注入通过property或setter方法

时间:2018-03-05 14:05:39

标签: c# dependency-injection asp.net-core-2.0 asp.net-core-mvc-2.0

它有been well documented,如何将依赖项注入服务。

问题但是,在ASP.NET Core 2.0中是否(已经)可以让系统的DI机制自动将服务注入方法或属性?

旁注:在PHP-Symfony中,这种模式称为setter injection

示例: 假设我的项目中的所有控制器都有一个公共MyBaseController类,我希望将一个服务(例如UserManager服务)注入MyBaseController,以后可以在所有子控制器中访问。我可以使用构造函数注入将服务注入子类,并通过base(userManager)将其传递给父类。但是必须在所有控制器的所有子构造器中执行此操作非常繁琐。

所以我希望像MyBaseController这样设置一个setter:

public abstract class MyBaseController : Controller
{
  public UserManager<User> userManager { get; set; }

  // system should auto inject UserManager here
  public void setUserManager(UserManager<User> userManager) {
    this.userManager = userManager;
  }
}

...所以我不必在每个子构造函数中执行以下操作只是为了将依赖项传递给父级:

public class UsersController : MyBaseController
{
  public ChildController(UserManager<User> userManager) : base(userManager) {}

更新:给出here的答案是我想要实现的,但问题是ASP.NET Core 1.0,我对ASP.NET Core 2.0中是否添加了任何解决方案感兴趣。

3 个答案:

答案 0 :(得分:4)

一般来说,避免非构造函数DI是一个很好的建议,因为它被认为是一种反模式,在related question中有一个很好的讨论。

使用aspnet核心中的默认Microsoft.Extensions.DependencyInjection容器,答案是否定的,但是如果您确定需要此功能,则可以更换为autofac (which has property injection)等更强大的功能。

答案 1 :(得分:0)

还有一种使用属性注入的方法,即使您可以与 Microsoft.Extensions.DependencyInjection 一起使用而无需更改IoC提供程序。

.Nurse Injector支持它: https://github.com/enisn/DotNurseInjector#propertyfield-injection

您可以通过3个步骤来实现它:

  • 安装软件包DotNurse.Injector.AspNetCore
  • Program.cs
  • 中调用以下方法
 public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseDotNurseInjector() // <-- Add this method
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
  • 然后您可以使用[InjectService]属性代替构造函数注入:
[InjectService] public IBookRepository BookRepository { get; set; }

答案 2 :(得分:0)

您有两种DI

  1. 必须的,它是对象初始化所需的注入,然后是在构造函数中设置的注入。
  2. 可选,需要采取措施才能进行注射。

如果DI表现良好,您可以在不使用注射系统的情况下进行单元测试,如果所有注射都在ctor中,那么您将无休无止地中断每个单元测试。

因此,所有在ctor中的进样都违反了打开/关闭原则。

还有一点是,DI是用于接口实现或模块公共部分的,该实现下的对象是手动初始化的。

所以setter不错,因为它被界面隐藏了。