1

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)
Barbaros Alp
  • 6,405
  • 8
  • 47
  • 61

1 Answers1

1

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)
{

}
MichaC
  • 13,104
  • 2
  • 44
  • 56
  • Ohh, this has been the trick from the very begining: [Dependency("runtimeCache")] Because of not knowing this feature(haven't used named injection before), I was trying to find a work around. Thank you so much, again! – Barbaros Alp Mar 18 '17 at 11:24