3

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 in Castle Windsor DI for IRepository<T>, if T is ISuperType, then provide ISuperRepository<T>. Else, provide IRepository<T>.

So for example, if A : ISuperType, then I want Resolve<IRepository<A>> to provide SuperRepository<A>, and Resolve<IRepository<B>> to provide Repository<B>.

How can I achive that?

Rita
  • 1,448
  • 1
  • 14
  • 22

2 Answers2

2

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 the registration:

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

And the resolve will:

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

Another option is to the extra parameter in Component.For. Then gets all type which inherite form the Type(For example) and register 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;
}
Community
  • 1
  • 1
Old Fox
  • 8,629
  • 4
  • 34
  • 52
  • Thanks for the response - I have many classes that implement ISuperType so I like the second approach, but it doesn't seem work - the resolved type is always SuperRepository and not Repository. – Rita Jul 20 '15 at 06:52
  • @Rita How your `Resolve` looks? If the `Resolve` looks like my example it should be work(It worked in my computer) – Old Fox Jul 20 '15 at 07:14
  • @Rita one more thing, verify that you didn't register something before the foreach, if you did so, you have to use the `Default()` extension method. – Old Fox Jul 20 '15 at 07:19
  • I couldn't get that to work. Component.For(typeof(IRepository<>),type) was completely ignoring the type. I ended up registering with MakeGenericType. I'd appreciate if you can tell me what the problem is. Anyway, this is the code and it works for me: foreach (var type in types) { container.Register(Component.For(typeof (IRepository<>).MakeGenericType(type)) .ImplementedBy(typeof (SuperRepository<>).MakeGenericType(type))); } – Rita Jul 20 '15 at 16:03
  • I forgot to mention, I also need registration of Component.For(typeof(ISuperRepository<>)).ImplementedBy(typeof(SuperRepository<>). – Rita Jul 20 '15 at 16:06
-1

You can restrict what types a generic is used for with the "where T: typename" syntax, where "typename" refers to a type the specified type 'T' must inherit (or implement). In your case "where T: ISuperType" would match the specific types, and a version without the restriction should match all the rest.

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

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

tamlin
  • 21
  • 1
  • 1
    This is not the problem I'm having. I'm looking for a way to do a conditional registration in Castle Windsor DI. – Rita Jul 19 '15 at 15:29
  • Provided "registration" means "running code" (while I have a cursory understanding of the subject, I've never delved deeper into it), what would be preventing from testing if T is of type ISuperType? I'm here assuming there's a small "factory" for these repository objects, so it can select the right one. – tamlin Jul 19 '15 at 16:22
  • 2
    @tamlin You might want to learn [what DI is in general](https://en.wikipedia.org/wiki/Dependency_injection) and what [Castle Windsor](https://github.com/castleproject/Windsor/blob/master/docs/README.md) is in particular. – GSerg Jul 19 '15 at 16:38