Замок Виндзор: условное оформление открытых дженериков

У меня есть следующее:

class Repository<T> : IRepository<T>
interface ISuperRepository<T> : IRepository<T>
class SuperRepository<T> : ISuperRepository<T>
interface ISuperType

Я хочу условную регистрацию в замке Виндзор Д.И. для IRepository<T>, если T является ISuperType, а затем предоставить ISuperRepository<T>, Остальное обеспечим IRepository<T>.

Так, например, если A : ISuperTypeтогда я хочу Resolve<IRepository<A>> предоставлять SuperRepository<A>, а также Resolve<IRepository<B>> предоставлять Repository<B>,

Как я могу достичь этого?

2 ответа

Решение

Castle Windsor не поддерживает такую ​​вещь, однако вы можете достичь этого с помощью простого вспомогательного метода:

public static void RegisterAccordingToISuperType<T>(this IWindsorContainer container)
{
    if (typeof (T).GetInterfaces().Contains(typeof (ISuperType)))
        container.Register(Component.For<IRepository<T>>()
                                    .ImplementedBy<SuperRepository<T>>());
    else
        container.Register(Component.For<IRepository<T>>()
                                    .ImplementedBy<Repository<T>>());
}

Тогда регистрация:

container.RegisterAccordingToISuperType<SuperType>();
container.RegisterAccordingToISuperType<int>();

И решимость будет:

var super = container.Resolve<IRepository<SuperType>>();
var intRepo = container.Resolve<IRepository<int>>();

Другим вариантом является дополнительный параметр в Component.For, Затем получает все типы, которые наследуют тип ( например) и регистрируют их.

private static void Register(...)
{
    foreach (var type in GetInheriteTypes())
    {          
        container.Register(Component.For(typeof(IRepository<>),type)
                                    .ImplementedBy(typeof(SuperRepository<>)));
    }
    container.Register(Component.For(typeof(IRepository<>))
                                .ImplementedBy(typeof(Repository<>)));
}

private static IEnumerable<Type> GetInheriteTypes()
{
    var listOfBs = (from domainAssembly in AppDomain.CurrentDomain.GetAssemblies()
                    from assemblyType in domainAssembly.GetTypes()
                    where assemblyType.GetInterfaces().Contains(typeof(ISuperType))
                    select assemblyType).ToArray();
    return listOfBs;
}

Вы можете ограничить типы, для которых используется шаблон, с помощью синтаксиса "где T: имя-типа", где "имя-типа" относится к типу, который указанный тип "T" должен наследовать (или реализовывать). В вашем случае "где T: ISuperType" будет соответствовать конкретным типам, а версия без ограничения должна соответствовать всем остальным.

ссылка https://msdn.microsoft.com/en-us/library/bb384067.aspx

Если это невозможно сделать во время компиляции, это всегда можно сделать во время выполнения (с помощью f.ex. 'is').

Другие вопросы по тегам