我的 ASP.NET Core 应用程序中有一个带有多个构造函数的标签助手。当 ASP.NET 5 尝试解析类型时,这会在运行时导致以下错误:
InvalidOperationException:在“MyNameSpace.MyTagHelper”类型中找到了接受所有给定参数类型的多个构造函数。应该只有一个适用的构造函数。
其中一个构造函数是无参数的,另一个具有一些参数不是注册类型的参数。我希望它使用无参数构造函数。
有没有办法让 ASP.NET 5 依赖注入框架选择特定的构造函数?通常这是通过使用属性来完成的,但我找不到任何东西。
我的用例是我正在尝试创建一个既是 TagHelper 又是 HTML 帮助器的类,如果解决了这个问题,这是完全可能的。
MyTagHelper
是第三方或框架类型,请使用工厂委托注册它并调用该委托中的特定构造函数。
将 ActivatorUtilitiesConstructorAttribute
应用于您希望 DI 使用的构造函数:
[ActivatorUtilitiesConstructor]
public MyClass(ICustomDependency d)
{
}
这需要使用 ActivatorUtilities
类来创建您的 MyClass
。从 .NET Core 3.1 开始,Microsoft 依赖注入框架在内部使用 ActivatorUtilities
;在旧版本中,您需要手动使用它:
services.AddScoped(sp => ActivatorUtilities.CreateInstance<MyClass>(sp));
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 个参数的那个。
ASP.NET Core 1.0 答案
对于无参数构造函数,其他答案仍然适用,即,如果您有一个具有无参数构造函数的类和一个带参数的构造函数,则会抛出问题中的异常。
如果您有两个带参数的构造函数,则行为是使用已知参数的第一个匹配构造函数。您可以查看 ConstructorMatcher
类的源代码以了解详细信息 here。
ASP.NET Core 答案
在他们修复/改进此问题之前,我最终得到了以下解决方法。
首先,在你的控制器中只声明一个构造函数(只传递你需要的配置设置),考虑到构造函数中传递的设置对象可以为空(如果你在 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);
}
}
}
然后,在您的测试方法中,您可以通过两种方式实例化控制器:
在构造测试对象时模拟 IOptions 对象构造在所有参数中传递 null,然后存根您将在测试中使用的依赖项。下面你有一个例子:
[TestClass] 公共类 MyControllerTests { Service.Controllers.MyController 控制器;模拟
从这一点开始,您可以在 .NET Core 中使用依赖注入和模拟进行全面测试。
希望能帮助到你
不定期副业成功案例分享