How to register a generic interface using TinyIOC

.net, c#, generics, inversion-of-control, tinyioc

Solution

As mentioned in my comment, TinyIoC has a bug in the resolution of Open Generics - it doesn't keep the resolved instances with different type parameters apart, and as all registrations are implicitly done with `.AsSingleton()` by default, it always returns the first instance of the generic type that was resolved for all subsequent resolution requests.

Due to this, the following doesn't work:

container.Register(typeof(IRepository<>), typeof(AzureRepository<>));

There is a workaround, however - make the registration transient:

container.Register(typeof(IRepository<>), typeof(AzureRepository<>)).AsMultiInstance();

This will create a new instance for each resolution request and properly honor the type parameter. The downside of this is that you also get a new instance each time you request the interface with a type parameter that has previously been resolved.

Edit

Confirmed. Open Generics resolution does use the `SingletonFactory` that once it has created an instance will always return that for subsequent resolutions. It doesn't know or care about Generics. For this to work properly, a `GenericSingletonFactory` would be required that does not only keep a single instance but a dictionary keyed by the concrete type to be resolved.

Alright, that wasn't even that hard to fix. I just don't understand enough about it yet to be sure that it's really all correct.

Problem

Suppose I have a generic interface and a generic implementation. How do I register all usages? Specifically, I have the following (reduced for simplicity): ``` public interface IRepository<T> where T : TableEntity { T GetById(string partitionKey, string rowKey); void Insert(T entity); void Update(T entity); void Update(string partitionKey, string rowKey, Action<T> updateAction); void Delete(T entity); IQueryable<T> Table { get; } } public class AzureRepository<T> : IRepository<T> where T : TableEntity { ... } ``` Do I need to register all implementations one by one, like so: ``` container.Register<IRepository<Entity1>, AzureRepository<Entity1>>(); container.Register<IRepository<Entity2>, AzureRepository<Entity2>>(); container.Register<IRepository<Entity3>, AzureRepository<Entity3>>(); ... ``` Or is there a shorter way?

Original source