3
votes

I'm trying to register the following combination in Simple Injector:

  1. Collection of (one or more) implementations of IMyInterface for a concrete type, e.g. Implementation1<MyClass> and Implementation2<MyClass> for IMyInterface<MyClass>
  2. Dummy collection (empty list) for the open generic type IMyInterface<T> as fall-back (conditional?)

This way I want to ensure that all requestors of IEnumerable<IMyInterface<T>> will get at least an empty list or the list of real implementations; requestor of IEnumerable<IMyInterface<MyClass>> should get enumerable instance (e.g. List<IMyInterface<MyClass>>) with the elements Implementation1<MyClass> and Implementation2<MyClass>, and requestor of IEnumerable<IMyInterface<AnotherClass>> should get Enumerable.Empty<IMyInterface<AnotherClass>>.

The list of classes is not fixed in the registration code. I've implemented a bootstrapper collecting all implementations from assemblies.

I tried using several combinations of RegisterCollection and RegisterConditional, but no one fulfilled all requirements. Is there a work-around for (not existing) RegisterCollectionConditional?

1
Can you explain (or show) what the conditions are for the implementations to show up in the collection or not? - Steven
Without that info it is impossible to supply you with a good answer. - Steven
@Steven, thans for your response! I think Issue 283 is not releated, because I'm working with an open generic collection. I've reworked the question description, hopefully with the requested inforamtion. - lg2de
You state that IEnumerable<IMyInterface<AnotherClass>> should be an empty list, while IEnumerable<IMyInterface<MyClass>> should have two implementations. But what are the exact conditions on which you wish to make IEnumerable<IMyInterface<AnotherClass>> empty? Do you have any type constraints on Implementation1<T> and Implementation2<T> that prevent Implementation1<AnotherClass> to be a valid type? - Steven

1 Answers

1
votes

Updated with v4.3 syntax.

What you want to do does not require anything special in Simple Injector; Simple Injector will automatically select any assignable type for you. Assuming the following types:

class Implementation1 : IMyInterface<MyClass> { }
class Implementation2 : IMyInterface<MyClass> { }
class Implementation3 : IMyInterface<FooBarClass>, IMyInterface<MyClass> { }

The registration would look as follows:

container.Collection.Register(typeof(IMyInterface<>),
    typeof(Implementation1),
    typeof(Implementation2),
    typeof(Implementation3));

This will result in the following:

// returns: Implementation1, Implementation2, Implementation3.
container.GetAllInstances<IMyInterface<MyClass>>();

// returns: Implementation3.
container.GetAllInstances<IMyInterface<FooBarClass>>();


// returns: empty list.
container.GetAllInstances<IMyInterface<AnotherClass>>();

Instead of registering all types manually, you can also use batch registration:

container.Collection.Register(typeof(IMyInterface<>),
    typeof(Implementation1).Assembly);

This will register all implementations (assuming they are all in the same assembly).

In case however you have the following types:

class Implementation1<T> : IMyInterface<T> { }
class Implementation2<T> : IMyInterface<T> { }
class Implementation3<T> : IMyInterface<T> { }

You can do the following registration:

container.Collection.Register(typeof(IMyInterface<>),
    typeof(Implementation1<MyClass>),
    typeof(Implementation2<MyClass>),
    typeof(Implementation3<MyClass>),
    typeof(Implementation3<FooBarClass>));

This registration would result in the same result as we've seen before:

// returns: Implementation1<MyClass>, Implementation2<MyClass>, Implementation3<MyClass>.
container.GetAllInstances<IMyInterface<MyClass>>();

// returns: Implementation3<FooBarClass>.
container.GetAllInstances<IMyInterface<FooBarClass>>();

// returns: empty list.
container.GetAllInstances<IMyInterface<AnotherClass>>();

For more information, see the collections section and the generic collections section in the documentation.