How to register a generic interface using TinyIOC

2019-06-16 04:42发布

问题:

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?

回答1:

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.