如何用LifetimeScopeLifestyle注册一个泛型类型的多个实现

本文关键字:泛型类型 一个 实现 LifetimeScopeLifestyle 注册 何用 | 更新日期: 2023-09-27 18:10:04

在SO上回答这个问题时,我无法找出在SimpleInjector中使用LifetimeScopeLifestyle实例注册许多泛型类型实现的最佳技术。

推荐的注册方法是这样的:

container.RegisterManyForOpenGeneric(typeof(IRepository<>), 
    typeof(IRepository<>).Assembly);

但是不允许传入LifetimeScopeLifestyle的实例

下面是我想到的,但我知道它没有足够的弹性,因为它正在检查任何通用接口,而不是特定的IRepository<>。有人能告诉我怎么做吗?

public static void Configure(Container container)
{
    var lifetimeScope = new LifetimeScopeLifestyle();
    container.Register<IUnitOfWork, UnitOfWork>(lifetimeScope);
    //this query needs improvement
    var registrations =
        from type in typeof(IRepository<>).Assembly.GetExportedTypes()
        where typeof(IRepository).IsAssignableFrom(type)
            && type.IsClass
            && !type.IsAbstract
        from service in type.GetInterfaces()
        where service.IsGenericType
        select new { Service = service, Implementation = type };
    foreach (var registration in registrations)
    {
        container.Register(registration.Service, 
            registration.Implementation, lifetimeScope);
    }
}

如何用LifetimeScopeLifestyle注册一个泛型类型的多个实现

TLDR:

container.RegisterManyForOpenGeneric(
    typeof(IRepository<>),
    lifetimeScope, 
    typeof(IRepository<>).Assembly);

首先,你的查询是错误的。它应该是:

var registrations =
    from type in
        typeof(IRepository<>).Assembly.GetExportedTypes()
    where !service.IsAbstract
    where !service.IsGenericTypeDefinition
    from @interface in type.GetInterfaces()
    where @interface.IsGenericType
    where @interface.GetGenericTypeDefinition() ==
        typeof(IRepository<>)
    select new { Service = @interface, Impl = type };

第二,框架包含一个GetTypesToRegister方法来为您获取这些类型,它不包括装饰器类型:

var repositoryTypes =
    OpenGenericBatchRegistrationExtensions.GetTypesToRegister(
        container, typeof(IRepository<>), 
        typeof(IRepository<>).Assembly);
var registrations =
    from type in repositoryTypes
    from @interface in type.GetInterfaces()
    where @interface.IsGenericType
    where @interface.GetGenericTypeDefinition() ==
        typeof(IRepository<>)
    select new { Service = @interface, Impl = type };

但是它变得更好,容器包含RegisterManyForOpenGeneric方法的重载,该方法接受一个回调委托,允许您按照以下方式进行注册:

container.RegisterManyForOpenGeneric(
    typeof(IRepository<>),
    (service, impls) =>
    {
        container.Register(service, impls.Single(),
            lifetimeScope);
    }, 
    typeof(IRepository<>).Assembly);

但最重要的是,该框架包含RegisterManyForOpenGeneric重载,它接受Lifetime。因此,您可以将注册简化为以下内容:

container.RegisterManyForOpenGeneric(
    typeof(IRepository<>),
    lifetimeScope, 
    typeof(IRepository<>).Assembly);