C# 当简单注入器只有一个具体的接口时,如何使其自动解析接口?

C# 当简单注入器只有一个具体的接口时,如何使其自动解析接口?,c#,asp.net-web-api,simple-injector,C#,Asp.net Web Api,Simple Injector,目前我有一个webapi控制器,其构造函数如下: readonly IQueryFactory queryFactory; readonly ICommandFactory commandFactory; public UserBenefitsController( IQueryFactory queryFactory, ICommandFactory commandFactory) { this.queryFactory = queryFactory; th

目前我有一个webapi控制器,其构造函数如下:

readonly IQueryFactory queryFactory;
readonly ICommandFactory commandFactory;

public UserBenefitsController(
    IQueryFactory queryFactory, 
    ICommandFactory commandFactory)
{
    this.queryFactory = queryFactory;
    this.commandFactory = commandFactory;
}
我使用简单的注入器来注册这两种类型

container.RegisterWebApiRequest<IQueryFactory, QueryFactory>();
container.RegisterWebApiRequest<ICommandFactory, CommandFactory>();
container.RegisterWebApiRequest();
container.RegisterWebApiRequest();
但我发现,随着我继续开发我的应用程序,我继续以1:1的比例将大量的
isomointerface
解析为
isomoconcrete


当WebApiRequest范围内只有一个具体接口时,是否可以告诉simple injector查找接口并自动解决它?

您可以使用批处理/自动注册来解决具体实例。 简单喷油器文档对此进行了解释

例如:

ScopedLifestyle scopedLifestyle = new WebApiRequestLifestyle();

var assembly = typeof(YourRepository).Assembly;

var registrations =
    from type in assembly.GetExportedTypes()
    where type.Namespace == "Acme.YourRepositories"
    where type.GetInterfaces().Any()
    select new
    {
        Service = type.GetInterfaces().Single(),
        Implementation = type
    };

foreach (var reg in registrations)
    container.Register(reg.Service, reg.Implementation, scopedLifestyle);
除了Bacardi先生的正确答案(可能更好)之外,您还可以使用未注册的类型解析,使用以下扩展方法来实现这一点:

public static void AutoMap(this Container container, params Assembly[] assemblies) {
    container.ResolveUnregisteredType += (s, e) => {
        if (e.UnregisteredServiceType.IsInterface && !e.Handled) {
            Type[] concreteTypes = (
                from assembly in assemblies
                from type in assembly.GetTypes()
                where !type.IsAbstract && !type.IsGenericType
                where e.UnregisteredServiceType.IsAssignableFrom(type)
                select type)
                .ToArray();

            if (concreteTypes.Length == 1) {
                e.Register(Lifestyle.Transient.CreateRegistration(concreteTypes[0], 
                    container));
            }
        }
    };
}
您可以按如下方式使用此扩展方法:

container.AutoMap(Assembly.GetExecutingAssembly());
必须对该方法应用一组严格的程序集,仅包含生产程序集。当您应用所有AppDomain程序集时,您会发现它很可能会在集成或单元测试套件中失败,因为这些程序集中很可能存在这些接口的伪实现

不过,我的偏好是尽可能多地进行明确的预先注册,这正是百加得先生所描述的解决方案。这里描述的方法使用“即时”方法,即在第一次解析时开始寻找实现。但是,如果调用
container.Verify()
,在大多数情况下都是安全的,尽管调用Verify()可能会成功,但在运行时解析对象图会失败,因为Verify()只会验证配置已知的对象。因此,您必须确保未注册的接口直接或间接地被实际注册的对象引用。因为很容易忽视这一点,我更喜欢巴拉迪先生的方法


但我必须承认,在我工作的应用程序(通常相当大)中,我们只有一些“一对一”的实现。系统中的大多数实现都实现了一个通用接口(如and),我几乎没有理由对这些非通用接口进行批注册。另一方面,Simple Injector使用了
Register
方法。

非常好的信息,非常感谢您花时间给出一个替代方案。当我在本节中这样做时,我得到了一个“序列包含多个元素”的异常。我使用了这个问题的第二个答案来解决我的问题。谢谢