具有多个构造函数的ASP.NET 5 MVC 6依赖注入

时间:2015-10-04 08:54:01

标签: asp.net dependency-injection asp.net-core asp.net-core-mvc

我的ASP.NET 5应用程序中有一个带有多个构造函数的标记助手。当ASP.NET 5尝试解析类型时,这会在运行时导致以下错误:

  

InvalidOperationException:在“MyNameSpace.MyTagHelper”类型中找到了接受所有给定参数类型的多个构造函数。应该只有一个适用的构造函数。

其中一个构造函数是无参数的,另一个构造函数的参数不是注册类型。我希望它使用无参数构造函数。

有没有办法让ASP.NET 5依赖注入框架选择特定的构造函数?通常这是通过使用属性完成的,但我找不到任何东西。

我的用例是我正在尝试创建一个既是TagHelper的单个类,也是一个HTML帮助程序,如果这个问题得到解决,这是完全可能的。

5 个答案:

答案 0 :(得分:16)

Illya是对的:内置解析器不支持暴露多个构造函数的类型......但是没有什么能阻止您注册代理来支持这种情况:

services.AddScoped<IService>(provider => {
    var dependency = provider.GetRequiredService<IDependency>();

    // You can select the constructor you want here.
    return new Service(dependency, "my string parameter");
});

注意:在更高版本中添加了对多个构造函数的支持,如其他答案所示。现在,DI堆栈将很乐意选择具有可解析的最多参数的构造函数。例如,如果你有2个构造函数 - 一个有3个参数指向服务而另一个有4个 - 它将更喜欢具有4个参数的构造函数。

答案 1 :(得分:2)

答案是否定的。 ASP.NET 5 DI不支持具有多个公共构造函数的类型。

Dependency Injection in ASP.NET Core (vNext)

Dependency Injection in ASP.NET vNext

答案 2 :(得分:1)

ASP.NET Core 1.0答案

对于无参数构造函数,其他答案仍然是正确的,即如果您的类具有无参数构造函数和带参数的构造函数,则将抛出问题中的异常。

如果有两个带参数的构造函数,则行为是使用已知参数的第一个匹配构造函数。您可以查看ConstructorMatcher类的源代码,了解详细信息here

答案 3 :(得分:1)

ASP.NET Core 2.1及更高版本

您可以在要在DI中使用的构造函数上使用ActivatorUtilitiesConstructorAttribute

[ActivatorUtilitiesConstructor]
public MyClass(ICustomDependency d)
{
}

答案 4 :(得分:0)

ASP.NET核心答案

我最终得到了以下解决方法,直到他们修复/改进了这一点。

首先,在控制器中只声明一个构造函数(仅传递所需的配置设置),考虑到构造函数中传递的设置对象可以为null(如果在Startup方法中配置它们,.NET Core会自动注入它们) :

public class MyController : Controller
{
    public IDependencyService Service { get; set; }

    public MyController(IOptions<MySettings> settings)
    {
        if (settings!= null && settings.Value != null)
        {
            Service = new DependencyServiceImpl(settings.Value);
        }
    }
}

然后,在测试方法中,您可以通过两种方式实例化控制器:

  1. 构造测试对象时模拟IOptions对象
  2. 构造在所有参数中传递null,然后Stub将在测试中使用的依赖项。下面是一个例子:
  3. [TestClass]
        public class MyControllerTests
        {
            Service.Controllers.MyController controller;
            Mock<IDependencyService> _serviceStub;
    
            [TestInitialize]
            public void Initialize()
            {
                _serviceStub = new Mock<IDependencyService>();
                controller = new Service.Controllers.MyController(null);
                controller.Service = _serviceStub.Object;
            }
        }
    

    从这一点开始,您可以使用依赖注入和.NET Core中的模拟进行全面测试。

    希望有所帮助