Autofac :来自单个接口和不同制造商的多个实现的解决方案
Autofac : Resolution from several implementation of a single interface and with different manufacturers
Autofac 是否可以实例化实现相同接口但具有不同构造函数的 classes,并且它可以推断实例化哪个 class?
public sealed class LoginModuleTypeItemViewModel : IInternalModuleTypeItemViewModel
{
public LoginModuleTypeItemViewModel(LoginModuleTypeExtraModel model)
{
}
}
public sealed class TypeObjectModuleTypeItemViewModel : IInternalModuleTypeItemViewModel
{
public TypeObjectModuleTypeItemViewModel(TypeObjectModuleTypeExtraModel model)
{
}
}
builder.RegisterType<TypeObjectModuleItemViewModel>().As<IInternalModuleItemViewModel>().SingleInstance();
builder.RegisterType<LoginModuleItemViewModel>().As<IInternalModuleItemViewModel>().SingleInstance();
_container.Resolve<IInternalModuleItemViewModel>(new TypedParameter(model.GetType(), model));
是的,这很好用。但一定要正确解析与构造函数中相同的类型(如果您使用 LoginModuleItemViewModel
注册,则模型必须为 LoginModuleTypeExtraModel
类型,除非您具有 [=12= 的有效构造函数] 在 LoginModuleItemViewModel
class).
当您注册多个组件(“类”)并公开相同的接口(“服务”)时,它最后获胜。这意味着,如果您有:
var builder = new ContainerBuilder();
builder.RegisterType<First>().As<IThing>();
builder.RegisterType<Second>().As<IThing>();
builder.RegisterType<Third>().As<IThing>();
var container = builder.Build();
那么当您尝试解析 IThing
时,它总是 是最后一个
var thing = container.Resolve<IThing>();
Assert.IsType<Third>(thing); // this is true
传递什么参数并不重要。如果您解决事物的单个实例,它将始终是最后的胜利。没有“select根据我传入的参数的东西。”如果你仔细想想,这是有道理的——从依赖注入/控制反转的角度来看,消费者永远不应该知道或关心实现接口的类型是什么。
如果你扩展你所要求的逻辑,如果你有这个会怎样?
public class First : IThing
{
public First(Dependency dep) : { }
}
public class Second : IThing
{
public Second(Dependency dep, OtherDependency other) : { }
}
然后你注册了...
var builder = new ContainerBuilder();
// We can resolve OtherDependency from the container
builder.RegisterType<OtherDependency>();
// The two things we'd pick from
builder.RegisterType<First>().As<IThing>();
builder.RegisterType<Second>().As<IThing>();
var container = builder.Build();
// OtherDependency can come from the container
// but you're providing the Dependency as a parameter
var thing = container.Resolve<IThing>(new TypedParameter(typeof(Dependency), new Dependency());
在那个例子中...thing
是什么类型?是 First
因为唯一的参数是 Dependency
吗?或者是 Second
因为标准的“最后获胜”并且因为 OtherDependency
可以来自容器?
如果是 First
那么...拥有依赖项注入容器有什么用,因为您实际上是在根据必须知道的构造函数参数“更新”特定类型无论如何?
如果它是 Second
那么......你没有得到你想要的东西,在那里你以某种方式得到“与构造函数参数匹配的东西”。
我知道上面没有给你答案但我希望它能让你明白为什么你要求的是Autofac(或任何 DI 容器)无法提供 - 你有一点设计问题。
您的问题涉及 on one of the Autofac FAQs 想知道如何“select 根据上下文实施。”
我的猜测是,在这条线上的某个地方,您有一个参数(或其他参数),并且您需要根据该参数“选择”不同的视图模型类型。
我链接到的常见问题解答解释了为什么这是一个设计问题,并提供了一些解决方法。我不会在这里重复整个事情,但简而言之:
- 您可以 redesign/change 使接口不相同。如果它们不能被视为相同,那么即使它们看起来具有相同的方法,它们也不是相同的。
- 您可以更新注册消耗各种事物的事物的方式,以便它们在某种程度上硬连线以采用它们期望的类型。这是一个复杂的事情,涉及
ResolvedParameters
和 lambda 注册,FAQ 页面上有一个工作示例来解释它。
- 您可以使用键控服务为每个供应商的组件提供一个 ID,然后在属性中或在手动解析操作期间使用这些 keys/IDs 来指示您想要的内容。
- 您可以使用元数据将供应商 ID 或其他 ID 附加到每个供应商的注册,以便在运行时“挑选”出正确的支持组件。
Check out the FAQ for explanations and examples in code. 它深入解释了这些选项的工作原理。
Autofac 是否可以实例化实现相同接口但具有不同构造函数的 classes,并且它可以推断实例化哪个 class?
public sealed class LoginModuleTypeItemViewModel : IInternalModuleTypeItemViewModel
{
public LoginModuleTypeItemViewModel(LoginModuleTypeExtraModel model)
{
}
}
public sealed class TypeObjectModuleTypeItemViewModel : IInternalModuleTypeItemViewModel
{
public TypeObjectModuleTypeItemViewModel(TypeObjectModuleTypeExtraModel model)
{
}
}
builder.RegisterType<TypeObjectModuleItemViewModel>().As<IInternalModuleItemViewModel>().SingleInstance();
builder.RegisterType<LoginModuleItemViewModel>().As<IInternalModuleItemViewModel>().SingleInstance();
_container.Resolve<IInternalModuleItemViewModel>(new TypedParameter(model.GetType(), model));
是的,这很好用。但一定要正确解析与构造函数中相同的类型(如果您使用 LoginModuleItemViewModel
注册,则模型必须为 LoginModuleTypeExtraModel
类型,除非您具有 [=12= 的有效构造函数] 在 LoginModuleItemViewModel
class).
当您注册多个组件(“类”)并公开相同的接口(“服务”)时,它最后获胜。这意味着,如果您有:
var builder = new ContainerBuilder();
builder.RegisterType<First>().As<IThing>();
builder.RegisterType<Second>().As<IThing>();
builder.RegisterType<Third>().As<IThing>();
var container = builder.Build();
那么当您尝试解析 IThing
时,它总是 是最后一个
var thing = container.Resolve<IThing>();
Assert.IsType<Third>(thing); // this is true
传递什么参数并不重要。如果您解决事物的单个实例,它将始终是最后的胜利。没有“select根据我传入的参数的东西。”如果你仔细想想,这是有道理的——从依赖注入/控制反转的角度来看,消费者永远不应该知道或关心实现接口的类型是什么。
如果你扩展你所要求的逻辑,如果你有这个会怎样?
public class First : IThing
{
public First(Dependency dep) : { }
}
public class Second : IThing
{
public Second(Dependency dep, OtherDependency other) : { }
}
然后你注册了...
var builder = new ContainerBuilder();
// We can resolve OtherDependency from the container
builder.RegisterType<OtherDependency>();
// The two things we'd pick from
builder.RegisterType<First>().As<IThing>();
builder.RegisterType<Second>().As<IThing>();
var container = builder.Build();
// OtherDependency can come from the container
// but you're providing the Dependency as a parameter
var thing = container.Resolve<IThing>(new TypedParameter(typeof(Dependency), new Dependency());
在那个例子中...thing
是什么类型?是 First
因为唯一的参数是 Dependency
吗?或者是 Second
因为标准的“最后获胜”并且因为 OtherDependency
可以来自容器?
如果是 First
那么...拥有依赖项注入容器有什么用,因为您实际上是在根据必须知道的构造函数参数“更新”特定类型无论如何?
如果它是 Second
那么......你没有得到你想要的东西,在那里你以某种方式得到“与构造函数参数匹配的东西”。
我知道上面没有给你答案但我希望它能让你明白为什么你要求的是Autofac(或任何 DI 容器)无法提供 - 你有一点设计问题。
您的问题涉及 on one of the Autofac FAQs 想知道如何“select 根据上下文实施。”
我的猜测是,在这条线上的某个地方,您有一个参数(或其他参数),并且您需要根据该参数“选择”不同的视图模型类型。
我链接到的常见问题解答解释了为什么这是一个设计问题,并提供了一些解决方法。我不会在这里重复整个事情,但简而言之:
- 您可以 redesign/change 使接口不相同。如果它们不能被视为相同,那么即使它们看起来具有相同的方法,它们也不是相同的。
- 您可以更新注册消耗各种事物的事物的方式,以便它们在某种程度上硬连线以采用它们期望的类型。这是一个复杂的事情,涉及
ResolvedParameters
和 lambda 注册,FAQ 页面上有一个工作示例来解释它。 - 您可以使用键控服务为每个供应商的组件提供一个 ID,然后在属性中或在手动解析操作期间使用这些 keys/IDs 来指示您想要的内容。
- 您可以使用元数据将供应商 ID 或其他 ID 附加到每个供应商的注册,以便在运行时“挑选”出正确的支持组件。
Check out the FAQ for explanations and examples in code. 它深入解释了这些选项的工作原理。