Castle Windsor: Conditional registration of open types

I have the following:

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

      

I want conditional registration with Castle Windsor DI for IRepository<T>

if T

- ISuperType

then specify ISuperRepository<T>

. Otherwise specifyIRepository<T>.

So, for example, if A : ISuperType

, then I want to Resolve<IRepository<A>>

provide SuperRepository<A>

and Resolve<IRepository<B>>

to provide Repository<B>

.

How can I achieve this?

+3


source to share


2 answers


Castle Windsor

doesn't support such a thing, however you can achieve it with a simple helper method:

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>>());
}

      

Then registration:

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

      



And the solution would be:

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

      

Another option is an optional parameter in Component.For

. It then gets all types that inherit from the Type ( For example ) and registers them.

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;
}

      

+2


source


You can restrict the types that a generic type is used with with the syntax "where T: typename", where "typename" refers to the type that the specified type "T" should inherit (or implement). In your case, "where T: ISuperType" will match specific types, and the unconstrained version should match all others.

ref. https://msdn.microsoft.com/en-us/library/bb384067.aspx



If it cannot be done at compile time, it can always be done at runtime (with f.ex. 'is').

-1


source







All Articles