Imagine that I have interfaces like below which all inherits from ICacheManager<>
public interface ICacheManagerRuntime<T> : ICacheManager<T>
public interface ICacheManagerRedis<T> : ICacheManager<T>
public interface ICacheManagerRedisWithRuntime<T> : ICacheManager<T>
I want to inject ICacheManager{CacheType} interfaces to implemantation of Cache classes like:
CacheRuntime, CacheRedis, CacheRedisWithRuntime
With unity I want to inject them like below:
container.RegisterType<ICacheManagerRuntime<object>>(
new ContainerControlledLifetimeManager(),
new InjectionFactory((c, t, n) =>
{
return CacheFactory.Build... // Return CacheManager just with RuntimeCacheHandle
})));
container.RegisterType<ICacheManagerRedis<object>>(
new ContainerControlledLifetimeManager(),
new InjectionFactory((c, t, n) =>
{
return CacheFactory.Build... // Return CacheManager just with RedisCacheHandle
})));
container.RegisterType<ICacheManagerRedisWithRuntime<object>>(
new ContainerControlledLifetimeManager(),
{
return CacheFactory.Build... // Return CacheManager just with RuntimeCacheHandleWithRedisBackPlane
})));
What ever I have done, I am getting this exception:
An unhandled exception of type 'Microsoft.Practices.Unity.ResolutionFailedException' occurred in Microsoft.Practices.Unity.dll
Additional information: Resolution of the dependency failed, type = "Solid.Play.Business.Interfaces.IProductService", name = "(none)".
Exception occurred while: Resolving parameter "cache" of constructor Solid.Play.Cache.Caches.CacheRuntime(Solid.Play.Cache.Interfaces.ICacheManagerRuntime`1[[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] cache).
Exception is: InvalidCastException - Unable to cast object of type 'CacheManager.Core.BaseCacheManager`1[System.Object]' to type 'Solid.Play.Cache.Interfaces.ICacheManagerRuntime`1[System.Object]'.
-----------------------------------------------
At the time of the exception, the container was:
Resolving Solid.Play.Business.Services.ProductService,(none) (mapped from Solid.Play.Business.Interfaces.IProductService, (none))
Resolving Solid.Play.Cache.Interception.CachingInterceptorBehavior,(none)
Resolving parameter "cache" of constructor Solid.Play.Cache.Interception.CachingInterceptorBehavior(Solid.Play.Cache.Interfaces.ICacheSolid cache)
Resolving Solid.Play.Cache.Caches.CacheSolid,(none) (mapped from Solid.Play.Cache.Interfaces.ICacheSolid, (none))
Resolving parameter "cacheRuntime" of constructor Solid.Play.Cache.Caches.CacheSolid(Solid.Play.Cache.Interfaces.ICacheRuntime cacheRuntime, Solid.Play.Cache.Interfaces.ICacheRedis cacheRedis, Solid.Play.Cache.Interfaces.ICacheRedisWithRuntime cacheRedisWithRuntime)
Resolving Solid.Play.Cache.Caches.CacheRuntime,(none) (mapped from Solid.Play.Cache.Interfaces.ICacheRuntime, (none))
Resolving parameter "cache" of constructor Solid.Play.Cache.Caches.CacheRuntime(Solid.Play.Cache.Interfaces.ICacheManagerRuntime`1[[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] cache)
The cast does not work because you are trying to cast an instance to an interface it does not implement. Simplified, what you are trying looks like this:
public interface IBase
{
}
public interface ISub : IBase { }
public class BaseClass : IBase
{
}
var sub = (ISub)new BaseClass();
If you want to inject different kind of instances of the same interfaces, the Unity DI framework provides a way to do that via named injection.
Example:
container.RegisterType<ICacheManager<object>>("runtimeCache",
new ContainerControlledLifetimeManager(),
new InjectionFactory((c, t, n) =>
{
return CacheFactory.Build<object>(s =>
{
s.WithSystemRuntimeCacheHandle("cache.runtime");
});
}));
container.RegisterType<ICacheManager<object>>("redisCache",
new ContainerControlledLifetimeManager(),
new InjectionFactory((c, t, n) =>
{
return CacheFactory.Build<object>(s =>
{
s.WithRedisConfiguration("cache.redis", config =>
{
config
.WithAllowAdmin()
.WithDatabase(0)
.WithEndpoint("localhost", 6379);
})
.WithRedisCacheHandle("cache.redis");
});
}));
To resolve the first one, you'd use
var runtimeCache = container.Resolve<ICacheManager<object>>("runtimeCache");
You can inject the ICacheManager interface to constructors with attributes for example.
public YourClass([Dependency("runtimeCache")] ICacheManager<object> cache)
{
}