Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to register a class that implements multiple interfaces in MVVM Light's SimpleIoc?

Let's say I have a couple of interfaces and a class that implements them:

public interface ISomething1 { /* blablabla */ }
public interface ISomething2 { /* blablabla */ }
public class Service : ISomething1, ISomething2 { /* blablabla x 2 */ }

I'd like to register the class in the SimpleIoc with both of these interfaces:

SimpleIoc.Default.Register<ISomething1, Service >();
SimpleIoc.Default.Register<ISomething2, Service >();

However the second line here throws an ArgumentException with the message:

An item with the same key has already been added.

I'd have thought that the key here is the interface itself, but apparently that's not the case. My idea was to use explicit keys however I'd like to get the instances via dependency injection, where the IoC can only work with keyless registries.

So how could I use SimpleIoc here without changing either of the interfaces or the implementation itself?

like image 843
pangabiMC Avatar asked Apr 02 '15 16:04

pangabiMC


2 Answers

Probably this is a better solution because Service() constructor can have dependencies registered in the ioc container.

SimpleIoc.Default.Register<Service>();
SimpleIoc.Default.Register<ISomething1>(() => SimpleIoc.Default.GetInstance<Service>());
SimpleIoc.Default.Register<ISomething2>(() => SimpleIoc.Default.GetInstance<Service>());
like image 64
Boogier Avatar answered Nov 14 '22 18:11

Boogier


Looking at the source code here (SimpleIoc.cs on CodePlex) has revealed what the problem was. When using this overload of the register function:

public void Register<TInterface, TClass>(bool createInstanceImmediately)

as anticipated it will add TInterface and TClass to a dictionary where the interface is the key, however it also adds TClass and its constructor to another dictionary where the class is the key without any further checks.

I suspect it is a bug as if TClass was already known (ie. added to this constructor lookup map) it could simply live with that.


Solution:

The solution / workaround is to use the factory type of registration. This works as expected:

SimpleIoc.Default.Register<ISomething1>(() => new Service());
SimpleIoc.Default.Register<ISomething2>(() => new Service());
like image 33
pangabiMC Avatar answered Nov 14 '22 19:11

pangabiMC