C# Autofac:从单个接口的多个实现和不同制造商的解决方案

C# Autofac:从单个接口的多个实现和不同制造商的解决方案,c#,autofac,C#,Autofac,Autofac是否可以实例化实现相同接口但具有不同构造函数的类,并推断要实例化的类 public sealed class LoginModuleTypeItemViewModel : IInternalModuleTypeItemViewModel { public LoginModuleTypeItemViewModel(LoginModuleTypeExtraModel model) { } } public sealed class TypeObjectModu

Autofac是否可以实例化实现相同接口但具有不同构造函数的类,并推断要实例化的类

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));
公共密封类LoginModuleTypeItemViewModel:IInternalModuleTypeItemViewModel
{
公共LoginModuleTypeItemViewModel(LoginModuleTypeExtraModel模型)
{
}
}
公共密封类TypeObjectModuleTypeItemViewModel:IInternalModuleTypeItemViewModel
{
公共类型ObjectModuleTypeItemViewModel(类型ObjectModuleTypeExtraModel)
{
}
}
builder.RegisterType().As().SingleInstance();
builder.RegisterType().As().SingleInstance();
_Resolve(新的TypedParameter(model.GetType(),model));

是的,这很好用。但请确保使用构造函数中的相同类型正确解析(如果您正在注册
LoginModuleItemViewModel
,则该模型必须为
LoginModuleTypeExtraModel
类型,除非您在
LoginModuleItemViewModel
类中具有
类型objectmoduletypeextramodel
的有效构造函数).

当您注册多个组件(“类”)以公开同一接口(“服务”)时,它是wins中的最后一个组件。也就是说,如果您有:

var builder=newcontainerbuilder();
builder.RegisterType().As();
builder.RegisterType().As();
builder.RegisterType().As();
var container=builder.Build();
然后,当你试图解决一个
问题时,它总是最后一个问题

var thing=container.Resolve();
Assert.IsType(thing);//这是真的
传递什么参数并不重要。如果你只解决一个实例,它将永远是wins中的最后一个。没有“根据我传入的参数选择对象”。如果你仔细想想,这是有意义的——从依赖注入/控制反转的角度来看,使用者永远不应该知道或关心实现接口的类型

如果你扩展你所要求的逻辑,如果你有这个呢

公共类优先:I
{
公共优先(依赖项部门):{}
}
公共课第二名:伊辛
{
公共秒(依赖项dep,其他依赖项其他):{}
}
然后你注册了

var builder=newcontainerbuilder();
//我们可以从容器中解析OtherDependency
RegisterType();
//我们从中挑选的两件事
builder.RegisterType().As();
builder.RegisterType().As();
var container=builder.Build();
//OtherDependency可以来自容器
//但您将依赖项作为参数提供
var thing=container.Resolve(新类型参数(typeof(Dependency),newdependency());
在那个例子中,…什么类型的
东西
?它是
第一个
,因为唯一的参数是
依赖项
?还是
第二个
,因为标准的“最后一个赢”和
其他依赖项
可以来自容器

如果它是
首先
然后…拥有依赖项注入容器有什么用,因为您实际上是基于您必须知道的构造函数参数“更新”特定类型

如果是
,那么……你没有得到你想要的,你不知何故得到了“与构造函数参数匹配的东西”

我知道上面的内容并没有给你一个答案,但我希望它能让你明白为什么你所要求的东西可能不是Autofac(或任何DI容器)所能提供的——你有一点设计问题

您的问题涉及到如何“根据上下文选择实现。”

我的猜测是,在这条线的某个地方,您有一个参数(或其他什么),基于此,您需要“选择”不同的视图模型类型

我链接到的常见问题解答解释了这是一个设计问题的原因,并提供了一些解决方法。我不会在这里重复全部内容,但简而言之:

  • 您可以重新设计/更改接口,使它们不完全相同。如果不能将它们视为完全相同,则即使它们看起来具有相同的方法,它们也不完全相同
  • 您可以更新注册使用各种物品的物品的方式,使它们在某种程度上符合预期的类型。这是一件涉及
    ResolvedParameters
    和lambda注册的复杂事情,FAQ页面上有一个工作示例来解释这一点
  • 您可以使用键控服务为每个供应商的组件提供一个ID,然后在属性中或在手动解析操作期间使用这些键/ID来指示您想要的东西
  • 您可以使用元数据将供应商ID或其他ID附加到每个供应商的注册中,以便在运行时“选择”正确的备份组件

  • 它深入解释了这些选项的工作原理。

    当我想实例化一个
    LoginModuleTypeItemViewModel
    时,“model”的类型是“LoginModuleTypeExtraModel”。与
    TypeObjectModuleTypeItemViewModel
    相同,“model”是类型
    TypeObjectModuleTypextramodel
    。但这目前不起作用,它只考虑最后注册的类型
    LoginModuleItemViewModel
    。你有办法解决这个问题吗?我认为@travis illig的上述回答澄清了一些问题,这首先是一个设计问题,而不是Autofac。