Wondering if it's possible to achieve the following:
container.GetInstance<IWordFacade<,,,>>();
So far I haven't been able to. Here are some code samples:
IWordFacade<T1,T2,T3,T4>{
T1 DoSomething(T2);
}
public class ConcreteFacade1 : IWordFacade<int,long,double,decimal>{
int DoSomething(long param){
//....
}
}
public class ConcreteFacade2 : IWordFacade<short,string,float,char>{
short DoSomething(string param){
// ...
}
}
... given these types/classes I am trying to find something that will allow me to return either ConcreteFacade1 or 2 based on how the container is configured to resolve the interface (which is where I'm having trouble).
I have tried:
container.Register(typeof(IWordFacade<,,,>), typeof(ConcreteFacade1));
resulting in an error stating: IWordFacade<,,,> is not a registered open generic type.
The code you supplied is not valid C# and will not compile. You can't specify an open-generic type within the < and > tags. You have to specify a closed generic type. The following however is valid C#:
container.GetInstance(typeof(IWordFacade<,,,>));
Although this would compile, this still will not work in Simple Injector (or any other DI framework), since frameworks always want to return you a concrete instance, but you can't create an instance for an open generic type, which is quite obvious, since an open-generic type is just a template. You need to fill in the blanks to be able to create an instance. In other words, you need a closed-generic type.
But how should the container know which closed-generic instance it should create given this open generic type? There is an endless number of possible permutations.
Although you can register an open-generic type like this:
container.Register(typeof(IWordFacade<,,,>), typeof(WordImpl<,,,>));
You will have to request for a closed-generic interface for your DI container to be able to resolve it:
container.GetInstance<IWordFacade<Foo, Bar, FooBar>>();
or
container.GetInstance(typeof(IWordFacade<Foo, Bar, FooBar>));
UPDATE
From your update I understand that there is that you either register ConcreteFacade1
or ConcreteFacade2
, based on the config file, but never both. To be able to do this (in C#) you need a non-generic interface, otherwise you will only be able to program against System.Object
, which is not very useful (and type-safe). So let your generic IWordFacade<T1,T2,T3,T4>
inherit from the following non-generic interface:
interface IWordFacade {
object DoSomething(object value);
}
This way you can make the following registration:
contianer.Register<IWordFacade, ConcreteFacade1>();
And you can resolve:
container.GetInstance<IWordFacade>();
Or of course inject IWordFacade
into the constructor of a different type.
You now need to implement two methods into the implementations. If you have several implementations, it gets useful to define a base class. This base class can implement the non-generic interface method:
public abstract class WordFacadeBase<T1, T2, T3, T4> : IWordFacade<T1, T2, T3, T4> {
public abstract T1 DoSomething(T2 value);
object IWordFacade.DoSomething(object value) {
return DoSomething(T2)value);
}
}