在Autofac中注册和解析具有不同TypeOf的不同参数构造函数



我有一个类,它有两个构造函数,在构造函数中有两个不同类型的参数,这在我只有一个构造函数之前都很有效,但一旦我创建了另一个构造函数并试图解决它,autofac就会崩溃,并说使用构造函数配置指定构造函数,我尝试在DI中注册构造函数,但第一次注册覆盖了第二次

builder.RegisterType<DeviceMasterPageViewModel>().UsingConstructor(typeof(DeviceListModel));
builder.RegisterType<DeviceMasterPageViewModel>().UsingConstructor(typeof(int));

这是我的课,有两个

public DeviceMasterPageViewModel(DeviceListModel scannendDevice)
{}
public DeviceMasterPageViewModel(int selectedDeviceID)
{}

我不明白我应该如何在DI中注册这个类,这样当我传递特定类型的参数时,指定类型的构造函数应该被称为

您只能通过一种方式向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>();

正如你所看到的,你可以根据传入的参数在那里做一些动态的工厂式逻辑

但是,同样,如果你完全避免这种情况,你的生活会轻松得多。

最新更新