2
votes

I have an assembly with a certain amount of implementations of the same generic interface. I register all of them in one shot using the following registration in Windsor:

Types
   .FromAssembly(Assembly.GetExecutingAssembly())
   .BasedOn(typeof(IQuery<,>))

Now I would like to get an array of all the registered implementations but if I try this Castle bombs:

container.ResolveAll(typeof (IQuery<,>))

Why?

2
What's the exception?Chris Mantle
Well the expectation is an array of this interface implementation, which is actually one if I inspect the container at runtime with debug. But if I try to resolveall using a generic interface castle throw an exception saying it cannot resolve array of generic interfaceRaffaeu
You can't resolve an open generic type, since Windsor has no idea what to create for you. You will have to specify a closed generic type, such as container.ResolveAll(typeof(IQuery<int, double>)).Steven

2 Answers

0
votes

@Steven is right, it is not possible to resolve generic types without knowing what types they embed. However there are two ways to sidestep the problem

Either you have a closed list of possible input and outputs types, on which you can iterate in order to resolve all specific combinations

for var Type1 in PossibleTypes1
    for var Type2 in PossibleTypes2
        var list = container.ResolveAll(typeof(IQuery<,>).MakeGenericType(Type1, Type2)

This is not really elegant but you can get all your queries. However I'd like to propose the second alternative.

If you want to resolve all your queries, you must have an operation you want to call on them, or some information you would like to get out. If so then this operation or information should exist inside a base non-generic interface that your generic interface inherits from. Let's say you want to get the operation name, you could do something like:

public interface IBaseQuery {
    string getOperationName(); // your common operation 
}

public interface IQuery<In, Out>: IBaseQuery {
}

You would then register your IQuery implementations against all their interfaces and resolve IBaseQuery to call the common implementation for all your queries.

0
votes

It does not work, because your services are registered as concrete types of implementations. Add the WithService.FromInterface() clause into you registration code, to register it as inteface abstractions. IMO it would not work either (with open generics resolution).