0
votes

Is the following possible with Simple Injector 4?

var types = container.GetTypesToRegister(typeof(IFoo<>), assemblies);
container.RegisterCollection(typeof(IFoo<>), types);

with

public interface IFoo<T> where T : IBar { ... }

and

public interface IBar { ... }

and in the assembly similar types can be found like the following:

public class Foo : IFoo<FooBar> { ... }

where

public class FooBar : IBar { ... }

The container verifies this registration. But when I do

container.GetAllInstances<IFoo<IBar>>();

Then the result is empty. My intention is to inject the following:

IEnumerable<IFoo<IBar>> foos

which I expect to return all closed type implementations of IFoo<> where the closed generic parameter is an implementation of IBar.

Also another point is that whenever I want to write a unit test for the service that consumes IEnumerable<IFoo<IBar>>, I'm trying to mock this with the following:

IEnumerable<IFoo<IBar>> collection = new[] { new Foo() };
new ConsumerService(collection);

Here the compiler has a hard time to convert the type Foo to IFoo<IBar>, which I think I understand (not sure..). But what I don't understand is that how Simple Injector would instantiate the types in the collection?

1
What is it you like to achieve? From the supplied code I don't really understand what it is you exactly want. The open generic parameter is always IBar so why do you want to get all isntances of IFoo<IBar>. Seems you just wanting to have ALL implementations and still you want them to be generic..? - Ric .Net
You second question demonstrates the problem Simple Injector has here! Remember Constraints are not part of the signature - Ric .Net
Thanks @Ric.Net for the reminder. Indeed, I think I tried to make generic parameter constraints part of my signature and that should be avoided. - QuantumHive

1 Answers

2
votes

To be able to achieve what you want, you will have to make your IFoo<T> interface variant.

The reason you get an empty list is because IFoo<IBar> is not assignable from IFoo<FooBar>. Try it out yourself: the C# compiler will not permit you to cast Foo to IFoo<IBar>.

To achieve this you will have to make IFoo<T> covariant. In other words, you need to define the interface as follows:

public interface IFoo<out T> { }

After you done this, you'll see that Simple Injector automatically resolves all instances for you as you'd expect.

Whether however it is useful for you to have an out type argument is a different question. One that I cannot answer, given the abstract description you gave.