Reputation: 805
I'm working on a memory caching application that can load different cache providers via configuration. I'm doing this by defining an interface and using a plugin model to load an assembly and class that parses a file and loads a class that matches the interface. I'd really like to define the interface and with a generic type that allows any object to be stored by the backing cache (whether that be a wrapper around third party cache client like Redis or NCache, or my own MemoryCache implementation ect.) with the ultimate goal of having a factory that I can point to a dll that wraps my caching methodology.
The issue that I am running into is errors about Generics when I use Activator to try to instantiate the plugin. Does anyone know a way to load a class with generics to an interface?
Basic interface
public interface ICacheProvider<T>
{
T Get(string key);
bool Set(string key, T value, TimeSpan expiration);
}
Factory calls to load
public static ICacheProvider<T> GetCacheProvider(string path, string className, string configuration)
{
...
Assembly asm = Assembly.LoadFile(path);
Type type = asm.GetType(className);
return Activator.CreateInstance(type, new object[] { configuration }) as ICacheProvider<T>;
...
}
Upvotes: 3
Views: 147
Reputation: 115769
Sorry, but I don't think this is good design (and I know this is not CodeReview SE).
ICacheProvider<T>
is not very usable, because there's nothing in it that would require a separate type for each cacheable object. The following is, IMO, much better, plus it relieves you of CreateInstance
headache:
public interface ICacheProvider
{
T Get<T>(string key);
bool Set<T>(string key, T value, TimeSpan expiration);
}
Going further, I'm more than sure that concrete implementations of ICacheProvider
work with plain object
s, regardless of their concrete type. With this, you can further simplify your contract to:
public interface ICacheProvider
{
object Get(string key);
bool Set(string key, object value, TimeSpan expiration);
}
and a couple extension methods:
public static class CacheProviderExtensions
{
public static T Get<T>(this ICacheProvider cacheProvider, string key);
public static bool Set<T>(this ICacheProvider cacheProvider, string key,
T value, TimeSpan expiration);
}
Now, one of the most common operations with caches is "get-or-add" behavior, which can be expressed as yet another method on ICacheProvider
:
object GetOrSet(string key, Func<object> valueProvider, TimeSpan expiration)
Upvotes: 6