c# - Autofac中注册和解析不同TypeOf的不同参数构造函数
问题描述
我有一个有 2 个构造函数的类,在构造函数中有 2 个不同类型的参数,这很好用,直到我有一个构造函数,但是一旦我创建另一个构造函数并尝试解决它,autofac 崩溃并说使用构造函数配置指定构造函数,我尝试在 DI 中注册构造函数,但第一个注册覆盖了第二个
builder.RegisterType<DeviceMasterPageViewModel>().UsingConstructor(typeof(DeviceListModel));
builder.RegisterType<DeviceMasterPageViewModel>().UsingConstructor(typeof(int));
这是我有 2 个构造函数的课程
public DeviceMasterPageViewModel(DeviceListModel scannendDevice)
{}
public DeviceMasterPageViewModel(int selectedDeviceID)
{}
我无法理解我应该如何在 DI 中注册这个类,以便当我传递特定类型的参数时,应该调用指定的 typeof 构造函数
解决方案
您只能通过一种方式向 Autofac 注册组件。最后注册获胜。这就是为什么当您尝试注册两次时它不起作用的原因。
通常,您尝试做的事情与 DI 并不真正兼容。DI 真的希望在您的对象上有一个构造函数,仅此而已。此外,您建议的其中一个构造函数中有一个原始类型 ( int
),这对于 DI 也不是很好。
如果 DI 允许两个构造函数......它如何选择?假设在解析上下文中,参数int
和参数DeviceListModel
都可用。哪个构造函数是正确的?
如果您int
在构造函数中使用......因为您实际上只能注册一个给定的注册System.Type
,这意味着您拥有的任何对象都int
将获得相同的int
值。那正确吗?
所以,说了这么多,假设你仍然真的希望这发生。您将不得不编写自己的一些逻辑。
该逻辑的一部分需要知道您期望构造函数参数来自哪里。它们是您正在解决的应该已经在容器中注册的东西吗?或者它们是你要传递的东西?
也就是说,您有两个基本场景:
# All the stuff the DMPVM needs is _registered_
var b = new ContainerBuilder();
b.Register(3).As<int>();
b.RegisterType<DeviceListModel>().AsSelf();
b.RegisterType<DeviceMasterPageViewModel>().AsSelf();
var c = b.Build();
var d = c.Resolve<DeviceMasterPageViewModel>();
或者
# You plan on _passing in_ the values
var b = new ContainerBuilder();
b.RegisterType<DeviceMasterPageViewModel>().AsSelf();
var c = b.Build();
var d = c.Resolve<DeviceMasterPageViewModel>(new TypedParameter(typeof(int), 3));
(这是评论中提出的问题的症结所在。了解这一点对于您将编写的自定义逻辑类型很重要。)
如果您假设所有内容都将被注册,那么您可能需要编写自己的IConstructorSelector
. Autofac 附带了两种,一种与最可用的参数匹配,另一种与特定的构造函数签名匹配。然后,您可以在注册期间提供您的构造函数选择器。
如何准确地写这将取决于你。我认为这不是一个好主意,它会有很多警告,比如如果你有很长的生命周期来解决组件会发生什么;以及它对应用性能有何影响;等等。这完全取决于你。
如果你传递参数,它会更容易一些。您可以注册一个 lambda,而不是编写构造函数选择器。查找参数并根据需要使用它们。这是记录在案的。
它可能是这样的:
b.Register((ctx, plist) => {
var intParam = plist
.OfType<TypedParameter>()
.Where(p => p.Type == typeof(int))
.FirstOrDefault();
if(intParam != null) {
return new DeviceMasterPageViewModel((int)intParam.Value);
}
// int param isn't found, do a similar search for the
// DeviceListModel parameter.
}).As<DeviceMasterPageViewModel>();
如您所见,您可以根据传入的参数在此处执行一些动态工厂样式逻辑。
但是,同样,如果你完全避免这种情况,你的生活会容易得多。
推荐阅读
- c# - 如何遍历 Windows 窗体控件
- python - 如何在一级上使用标签列表对多索引数据框进行切片
- hyperledger-fabric - Peers and Orderers:Hyperledger Fabric 中账本更新过程的第 3 阶段
- angular - 手动 url 调用的问题
- php - 如何在 WordPress中将 src 赋予标签中的图像
- listview - 为什么ListView必须被MaterialApp包裹?
- javascript - Google 表格 onEdit(e) 类型错误:无法读取属性
- javascript - 使用异步过滤和映射 Promise
- c# - 无法翻译 LINQ 表达式。要么以可翻译的形式重写查询,要么切换到客户端评估 EF Core 3.1
- node.js - 为什么这个 node.js 应用程序由 Heroku 在本地运行,但没有在 Heroku 中加载?