我的ASP.NET 5应用程序中有一个带有多个构造函数的标记助手。当ASP.NET 5尝试解析类型时,这会在运行时导致以下错误:
InvalidOperationException:在“MyNameSpace.MyTagHelper”类型中找到了接受所有给定参数类型的多个构造函数。应该只有一个适用的构造函数。
其中一个构造函数是无参数的,另一个构造函数的参数不是注册类型。我希望它使用无参数构造函数。
有没有办法让ASP.NET 5依赖注入框架选择特定的构造函数?通常这是通过使用属性完成的,但我找不到任何东西。
我的用例是我正在尝试创建一个既是TagHelper的单个类,也是一个HTML帮助程序,如果这个问题得到解决,这是完全可能的。
答案 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不支持具有多个公共构造函数的类型。
答案 2 :(得分:1)
对于无参数构造函数,其他答案仍然是正确的,即如果您的类具有无参数构造函数和带参数的构造函数,则将抛出问题中的异常。
如果有两个带参数的构造函数,则行为是使用已知参数的第一个匹配构造函数。您可以查看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);
}
}
}
然后,在测试方法中,您可以通过两种方式实例化控制器:
[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中的模拟进行全面测试。
希望有所帮助