I have a generic base class for value caching functionality.
public abstract class CachedValueProviderBase<T> : ICachedValueProvider<T> where T : class
{
private Cache Cache { set; get; }
protected string CacheKey { get; set; }
protected int CacheSpanInMinutes { get; set; }
private static readonly object _cacheLock = new object();
public T Values
{
get
{
T value = Cache[CacheKey] as T;
if (value == null)
{
lock (_cacheLock)
{
value = Cache[CacheKey] as T;
if (value == null)
{
value = InitializeCache();
}
}
}
return value;
}
}
protected CachedValueProviderBase()
{
Cache = HttpRuntime.Cache;
CacheSpanInMinutes = 15;
}
public T CacheValue(T value)
{
if (value != null)
{
lock (_cacheLock)
{
Cache.Insert(CacheKey, value, null, DateTime.UtcNow.AddMinutes(CacheSpanInMinutes),
Cache.NoSlidingExpiration);
}
}
return value;
}
private T InitializeCache()
{
T value = Initialize();
CacheValue(value);
return value;
}
protected abstract T Initialize();
}
I have several classes that make use of this base class and as long as the T is different it is fine. When two sub classes use the same T, string for example, they share the same cache lock object. What is the best way of implementing the logic in a base class but still giving each sub class it's own cache lock object?
Update
After the suggestions below I have updated my class:
public abstract class CachedValueProviderBase<T> : ICachedValueProvider<T> where T : class
{
private Cache Cache { set; get; }
protected string CacheKey { get; set; }
protected int CacheSpanInMinutes { get; set; }
private object _cacheLock = new object();
public T Values
{
get
{
T value = Cache[CacheKey] as T;
if (value == null)
{
lock (_cacheLock)
{
value = Cache[CacheKey] as T;
if (value == null)
{
value = InitializeCache();
}
}
}
return value;
}
}
protected CachedValueProviderBase()
{
Cache = HttpRuntime.Cache;
CacheSpanInMinutes = 15;
}
public T CacheValue(T value)
{
if (value != null)
{
Cache.Insert(CacheKey, value, null, DateTime.UtcNow.AddMinutes(CacheSpanInMinutes),
Cache.NoSlidingExpiration);
}
return value;
}
private T InitializeCache()
{
T value = Initialize();
CacheValue(value);
return value;
}
protected abstract T Initialize();
}
}
My sub classes are now singletons so I could get rid of the static cachelock object making it an instance variable.
I had to take a good look at your code, to find out if it was correct. Once I noticed your cache is a HttpRuntime.Cache, it made sense. The HttpRuntime.Cache is thread-safe. Otherwise you would have had several thread-safety problems. With your current, code I advice you to do the following:
private string CacheKey { get; set; }
protected CachedValueProviderBase(string cacheKey)
{
this.CacheKey = cacheKey + "_" + typeof(T).FullName;
}
By supplying the cacheKey as constructor argument and making the property private (or readonly would do), you prevent it from being changed by later on. By appending the type name to the key, you prevent cache conflicts since everybody is using the same cache.
One last note. The lock in the CacheValue method is redundant, since the Cache is thread-safe.
Well, just remove the static modifier on your cacheLock object.
That keyword forces the field to be shared between all instances of subclasses that share the same generic parameter type.
If you remove it, the cacheLock object will be private to each instance of a subclass, regardless of the generic parameter's type.
private static readonly object _cacheLock = new object();
Should be :
private readonly object _cacheLock = new object();
Hope that helps
I handled this by implementing an abstract method in my base class GetCacheLockObject().
protected abstract object GetCacheLockObject();
Each derived class then returns its own reference to the cache lock object:
private static readonly object _cacheLockObject = new Object();
protected override object GetCacheLockObject()
{
return _cacheLockObject;
}
Calls to lock in the shared base class caching code then reference this method rather than an object in the base class.
Related
I am looking for a way to cast object variable into type with generic type argument specified by other variable of type Type.
I am limited to .NET 3.5, so no dynamic can be used :(
Main idea here is that I have access to a dictionary:
Dictionary<Type, object> data;
Data to that dictionary is added only in form of:
data.Add(T, new DataSub<T>(someValueOfTypeT));
The problem is, that when I'm trying to reverse the process:
foreach(var dataType in data.Keys) {
var dataValue = data[dataType];
ProcessDataValue(dataType, dataValue);
}
Now the question is how do I manage to cast object to DataSub?
Simplified DataSub.cs:
public class DataSub<T>
{
private T _cache;
public T Value {
get { return _cache; }
set { _cache = value; }
}
}
How it could work in ProcessDataValue:
public void ProcessDataValue(Type dataType, object dataValue)
{
var data = dataValue as DataSub<dataType>;
if (data == null) return;
AddProcessedDataValue(dataType, data.Value.ToString());
}
if you can do minimal changes to the classes you posted and if - as is showed in your example - what you would do with DataSub.Value is invoking ToString, may be you can obtain the result you need with
public interface IDataSub {
bool MatchesType(Type t);
object GetValue();
}
public class DataSub<T> : IDataSub {
private T _cache;
public T Value {
get { return _cache; }
set { _cache = value; }
}
public bool MatchesType(Type t) {
return typeof(T) == t; // or something similar, in order to handle inheritance
}
public object GetValue() {
return Value;
}
}
public class Client {
Dictionary<Type, IDataSub> data = new Dictionary<Type, IDataSub>() ;
public void AddData<T>(T someValueOfTypeT) {
data.Add(typeof(T), new DataSub<T> { Value = someValueOfTypeT });
}
public void UseData() {
foreach(var dataType in data.Keys) {
var dataValue = data[dataType];
ProcessDataValue(dataType, dataValue);
}
}
public void ProcessDataValue(Type dataType, IDataSub dataValue)
{
if(dataValue.MatchesType(dataType))
AddProcessedDataValue(dataType, dataValue.GetValue().ToString());
}
}
If the usage of DataSub.Value.ToString is only an example, and in the real world you need to access DataSub.Value using its type T, you should apply a broader reworking of you code.
What do you think about the following approach? This is an application of the pattern I like call set of responsibility (I wrote the linked post about this topic), a variation of GoF's chain of responsibility:
public interface IDataSub {
object GetValue();
}
public class DataSub<T> : IDataSub {
private T _cache;
public T Value {
get { return _cache; }
set { _cache = value; }
}
public object GetValue() {
return Value;
}
}
public interface IDataHandler {
bool CanHandle(Type type);
void Handle(object data);
}
public class Client {
private readonly Dictionary<Type, IDataSub> data = new Dictionary<Type, IDataSub>();
private readonly IList<IDataHandler> handlers = new List<IDataHandler>();
public void AddData<T>(T someValueOfTypeT) {
data.Add(typeof(T), new DataSub<T> { Value = someValueOfTypeT });
}
public void RegisterHandler(IDataHandler handler) {
handlers.Add(handler);
}
public void UseData() {
foreach(var dataType in data.Keys) {
handlers.FirstOrDefault(h => h.CanHandle(dataType))?.Handle(data[dataType].GetValue());
}
}
// Lambda-free version
// public void UseData() {
// foreach(var dataType in data.Keys) {
// for (int i = 0; i < handlers.Count; i++) {
// if (handlers[i].CanHandle(dataType)) {
// handlers[i].Handle(data[dataType].GetValue());
// break; // I don't like breaks very much...
// }
// }
// }
// }
}
class StringDataHandler : IDataHandler {
public bool CanHandle(Type type) {
// Your logic to check if this handler implements logic applyable to instances of type
return typeof(string) == type;
}
public void Handle(object data) {
string value = (string) data;
// Do something with string
}
}
class IntDataHandler : IDataHandler {
public bool CanHandle(Type type) {
// Your logic to check if this handler implements logic applyable to instances of type
return typeof(int) == type;
}
public void Handle(object data) {
int value = (int) data;
// Do something with int
}
}
This approach allow you to decouple data storage and data iteration logic from data-handling logic specific of different data-types: IDataHandler's implementations known what type of data they can handle and cast generic object reference to desired type. If you prefer, you can merge CanHandle method into Handle method, remving the former method and changing UseData to
public void UseData() {
foreach(var dataType in data.Keys) {
foreach(var handler in handlers) {
handler.Handle(dataType, data[dataType].GetValue())
}
}
}
and handler implementations to
class IntDataHandler : IDataHandler {
public void Handle(Type dataType, object data) {
if(typeof(int) == type) {
int value = (int) data;
// Do something with int
}
}
}
This variant is slightly more type-safe, because in the first variant was already possibile to call Handle method without a previus call to CanHandle.
If you liked this approach, you can bring it forward, simplifying your data structure and converting data from IDictionary to IList:
public interface IDataSub {
object GetValue();
}
public class DataSub<T> : IDataSub {
private T _cache;
public T Value {
get { return _cache; }
set { _cache = value; }
}
public object GetValue() {
return Value;
}
}
public interface IDataHandler {
bool CanHandle(object data);
void Handle(object data);
}
public class Client {
private readonly IList<IDataSub> data = new List<IDataSub>();
private readonly IList<IDataHandler> handlers = new List<IDataHandler>();
public void AddData<T>(T someValueOfTypeT) {
data.Add(new DataSub<T> { Value = someValueOfTypeT });
}
public void RegisterHandler(IDataHandler handler) {
handlers.Add(handler);
}
public void UseData() {
foreach(var dataItem in data) {
var value = dataItem.GetValue();
handlers.FirstOrDefault(h => h.CanHandle(value))?.Handle(value);
}
}
// Lambda-free version as above...
class StringDataHandler : IDataHandler {
public bool CanHandle(object data) {
// Your logic to check if this handler implements logic applyable to instances of String
return data is string;
}
public void Handle(object data) {
string value = (string) data;
// Do something with string
}
}
class IntDataHandler : IDataHandler {
public bool CanHandle(Type type) {
// Your logic to check if this handler implements logic applyable to instances of int
return type is int;
}
public void Handle(object data) {
int value = (int) data;
// Do something with int
}
}
The CanHandle-free variant can simplify IDataHandler interface and its implementation in this case, too...
I hope my answer can help you resolving you design scenario; I build it upon an approach I like very much, because it allows to apply subtype-specific logic to instances of different classe, given they share a common superclass (as object in my code samples).
I am trying to implement a thread safe dictionary singleton class for caching purpose.
namespace SingletomDict
{
public sealed class MySingleton:IDisposable
{
private static readonly Lazy<MySingleton> coll = new Lazy<MySingleton>(() => new MySingleton());
private static Dictionary<string, object> mycoll;
public static MySingleton Instance
{
get
{
return coll.Value;
}
}
private MySingleton()
{
mycoll = new Dictionary<string, object>();
}
private void SetProperty<T>(string name, T value)
{
mycoll.Add(name, value);
}
private object GetProperty(string name)
{
object value = mycoll[name];
return value;
}
public dynamic this[string index]
{
get { return GetProperty(index); }
set { SetProperty(index, value); }
}
public void ReSet()
{
mycoll = new Dictionary<string, object>();
}
}
In the main method, I will be invoking the object as
MySingleton.Instance["LS"] = "AAA";
MySingleton.Instance["AB"] = "BBB";
MySingleton.Instance.ReSet();
I did some research to find the correct implementation. But I couldn't find the appropriate example. Thanks
First declare an interface that describes how you want to use this. Perhaps ICache with a get and set method. (I'd steer clear of dynamic.)
public interface ICache
{
T Get<T>(string key);
void Set(string key, object value);
}
Then write an implementation. Your implementation doesn't need to specify what the internals are.
public class Cache : ICache
{
private readonly ConcurrentDictionary<string, object> _cache
= new ConcurrentDictionary<string, object>();
public T Get<T>(string key)
{
object cached;
if(_cache.TryGetValue(key, out cached) && cached is T)
{
return(T) cached;
}
return default(T);
}
public void Set(string key, object value)
{
_cache.AddOrUpdate(key, value, (s, o) => value);
}
}
If you want to make this a singleton, you can make the constructor private and create a static singleton instance. I would lean toward not doing that. It's better for other classes to depend on the ICache interface than on the implementation, and an interface doesn't have static methods.
Depending on the interface means that you can substitute it with different implementations, like one that depends on MemoryCache.
public class InMemoryCache : ICache
{
private readonly MemoryCache _cache = MemoryCache.Default;
public T Get<T>(string key)
{
var cached = _cache[key];
return cached is T ? (T) cached : default(T);
}
public void Set(string key, object value)
{
_cache[key] = value;
}
}
If you use a dependency injection (IoC) container you can tell it which implementation of ICache to use for a class that needs an instance of it, and you can specify that the same instance should be provided each time. That way you get to use a single instance of your class as if it was a singleton without having to code it as a singleton.
Is the following tread safe in a singleton pattern? I used the fourth singleton pattern in http://csharpindepth.com/Articles/General/Singleton.aspx
I'm concerned using an output parameter will break the whole principal.
public sealed class eCacheContent
{
private static readonly eCacheContent instance = new eCacheContent();
private ICacheManager _Cache = CacheFactory.GetCacheManager(ConfigurationManager.AppSettings["ContentCache"].ToString());
// for access method control locking
private static object syncRoot = new object();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static eCacheContent() { }
private eCacheContent() { }
public static eCacheContent Instance
{
get
{
return instance;
}
}
public bool TryGetValue(string key, out eContent output)
{
lock (syncRoot)
{
if (Contains(key))
{
ObjectCloner helper = new ObjectCloner();
eContent tmp = (eContent)this._Cache.GetData(key);
output = helper.Clone(tmp);
return true;
}
output = new eContent();
return false;
}
}
public void Add(string key, object value)
{
// Initiase the helper class for cloning
if (CheckKeyIfValid(key))
{
ObjectCloner helper = new ObjectCloner();
// Remove if already exist
this.Remove(key);
// Add carbon copy
_Cache.Add(key, helper.Clone(value));
}
}
public void Flush()
{
_Cache.Flush();
}
private bool Contains(string key)
{
if (CheckKeyIfValid(key))
return _Cache.Contains(key);
else
return false;
}
private void Remove(string key)
{
if (Contains(key))
{
_Cache.Remove(key);
}
}
private bool CheckKeyIfValid(string key)
{
if ((key != null) && (key.Trim().Length != 0))
return true;
return false;
}
}
I'm concerned using an output parameter will break the whole principal.
In what way do you think an out parameter breaks the principle of a Singleton? By definition a singleton class "restricts the Instantiation of a class to one object" - your Instance property ensures that.
Your TryGetValue method is a helper method for pulling out cached versions of eContent, this is completely separate from your eCacheContent class.
Suppose I have the following code.
static class Store<T> {
public static T A;
public static T B;
public static T C;
}
public static class Store {
public static Value A = new Value(<T>(v) => Store<T>.A = v); //just an example of what I want
public static Value B = new Value(<T>(v) => Store<T>.B = v); //just an example of what I want
public static Value C = new Value(SetC<T>); //just an example of what I want
public static void SetA<T>(T value) { Store<T>.A = value; }
public static void SetB<T>(T value) { Store<T>.B = value; }
public static void SetC<T>(T value) { Store<T>.C = value; }
}
public class Value {
Action<T><T> _valueChanger; //just an example of what I want
public Value(Action<T><T> valueChanger) { //just an example of what I want
_valueChanger = valueChanger;
}
public void SetValue<T> (T value) {
_valueChanger<T>(value); //just an example of what I want
}
}
I want to write Store.A.SetValue(42) so that the value is saved to Store<int>.A. What can I write instead of the lines marked by "just an example of what I want" to make that happen? (I want to explore a solution that doesn't involve dictionaries or something similar)
Rephrasing the question:
I want to modify class Value (define some fields, write a constructor and write the method Value.SetValue(T value) ), then construct three different variables of type Value (A, B, C) in such a way that when I call Store.A.SetValue(42) the value Store<int>.A is changed to 42.
Another variation of the classes:
static class Holder<T> {
T Value { get; set; }
}
static class Store2<T> {
public static Holder<T> A = new Holder<T>();
public static Holder<T> B = new Holder<T>();
public static Holder<T> C = new Holder<T>();
}
public static class Store2 {
public static Value A = new Value2(Store2<>.A); //just an example of what I want
public static Value B = new Value2(Store2<>.B); //passing non-specific generic expression
public static Value C = new Value3({TFree}() => Store2<TFree>.C); //just an example of what I want
}
public class Value2 { //Non-generic class!
Holder{TFree}<TFree> _holder; //just an example of what I want
public Value(Holder{TFree}<TFree> holder) { //just an example of what I want
_holder = holder;
}
public void SetValue<T> (T value) {
_holder{T}.Value = value; //just an example of what I want
}
}
public class Value3 { //Non-generic class! (Another variation)
Func{TFree}<Holder<TFree>> _holderFactory; //just an example of what I want
public Value(Func{TFree}<Holder<TFree>> holderFactory) { //just an example of what I want
_holderFactory = holderFactory;
}
public void SetValue<T> (T value) {
Holder<T> holder = _holderFactory{T}(); //just an example of what I want
holder.Value = value;
}
}
Solution:
An easy reflection-free and collection-free solution was found using the answers to another question ( Emulating delegates with free generic type parameters in C# and Emulating delegates with free generic type parameters in C#). The solution is Delegates to generic operations where the generic type is unknown. How to create something like that?.
Use an array to store the values and access them through a property using an index
public static class Store<T>
{
public static readonly T[] Values = new T[3];
public static T A { get { return Values[0]; } set { Values[0] = value; } }
public static T B { get { return Values[1]; } set { Values[1] = value; } }
public static T C { get { return Values[2]; } set { Values[2] = value; } }
}
public static class Store
{
public static readonly Value A = new Value(0);
public static readonly Value B = new Value(1);
public static readonly Value C = new Value(2);
}
public class Value
{
private int _index;
public Value(int index)
{
_index = index;
}
public void SetValue<T>(T value)
{
Store<T>.Values[_index] = value;
}
public T GetValue<T>()
{
return Store<T>.Values[_index];
}
}
Since the constructor of Value is not aware of any generic type parameter, you cannot have any reference to a specific Store<T>.
UPDATE
Be aware of the fact that a copy of Store<T> will be created for every distinct type argument that you supplied for T. See this example
Store.A.SetValue(42);
Store.A.SetValue("Douglas Adams");
Store.A.SetValue(new DirectoryInfo(#"C:\"));
Store.A.SetValue(new List<int>());
var x1 = Store.A.GetValue<int>(); // --> 42
var x2 = Store.A.GetValue<string>(); // --> "Douglas Adams"
var x3 = Store.A.GetValue<DirectoryInfo>(); // --> DirectoryInfo{ C:\ }
var x4 = Store.A.GetValue<List<int>>(); // --> List<int>{ Count = 0 }
By using the debugger, you will see that four different values are stored in A at the same time! Of cause these are four differents A's that exist in four diffferent Store<T>.
The problem turned out to be solvable. Mike-z gave me a nearly right solution for the delegate-to-generic-method problem ( Emulating delegates with free generic type parameters in C#) which I modified to be a full solution: ( Emulating delegates with free generic type parameters in C#).
The solution this question becomes easy too. Interfaces can contain generic methods and we can use the interface-valued variables to store links to generic methods without specifying concrete type arguments. The following code utilizes the Store<T> class without modifications and uses the ISetter interface and ASetter/BSetter/CSetter "closures" to hold references to different generic members. The Value class stores the references in a ISetter-typed variable and uses the generic member which the _setter links to once the type argument T becomes available.
public interface ISetter {
void SetValue<T>(T value);
}
public static class Store {
public static Value A = new Value(new ASetter());
public static Value B = new Value(new BSetter());
public static Value C = new Value(new CSetter());
class ASetter : ISetter {
public void SetValue<T>(T value) { Store<T>.A = value; }
}
class BSetter : ISetter {
public void SetValue<T>(T value) { Store<T>.B = value; }
}
class CSetter : ISetter {
public void SetValue<T>(T value) { Store<T>.C = value; }
}
}
public class Value {
ISetter _setter;
public Value(ISetter setter) {
_setter = setter;
}
public void SetValue<T> (T value) {
_setter.SetValue<T>(value);
}
}
I have a series of interface definitions, all of which compile (so my objects are composed correctly). The objects instantiate, as expected. However, when I try to return the object from its' underlying factory I get the following error:
ERROR:
Unable to cast object of type
'SampleLibrary.Domain.DataAcessors.Person.SQLDataAccessor' to type
'Common.Contracts.DataAccessors.IDataAccessorModel`2[SampleLibrary.Contracts.Models.IPerson,SampleLibrary.Domain.DataAccessors.Types.SqlServer]'.
Please keep in mind I am trying to return each instance as the IDataAccessor interface.
CODE:
public interface IDataAccessor<I, T>
{
T AccessType { get; }
}
public interface IDataAccessorModel<I, T> : IDataAccessor<I, T>
{
I Instance { get; }
IResult<string> Get(I instance);
IResult<string> Add(I instance);
IResult<string> Update(I instance);
IResult<string> Delete(I instance);
}
public class SQLDataAccessor : IDataAccessorModel<IPerson, IAccessType>
{
internal SQLDataAccessor(IResult<string> result)
{
_connectionString = "";
_result = result;
}
private readonly string _connectionString;
private IResult<string> _result;
public IAccessType AccessType { get { return new SqlServer(); } }
public IPerson Instance { get; private set; }
public IResult<string> Add(IPerson instance)
{
Instance = instance;
return _result;
}
public IResult<string> Get(IPerson instance)
{
Instance = instance;
return _result;
}
public IResult<string> Delete(IPerson instance)
{
Instance = instance;
return _result;
}
public IResult<string> Update(IPerson instance)
{
Instance = instance;
return _result;
}
}
public class FactoryDataAccess : IFactoryDataAccess
{
internal FactoryDataAccess() { }
public IDataAccessor<I, T> Create<I, T>()
{
var model = typeof(I);
var target = typeof(T);
if (model.IsAssignableFrom(typeof(IPerson)))
{
if (target == typeof(SqlServer)) {
var accessor = new Person.SQLDataAccessor(new Result());
// This next line FAILS!
return (IDataAccessorModel<I, T>)accessor;
}
}
throw new NotSupportedException("Type " + target.FullName + " and Source " + model.FullName + " is not supported.");
}
}
UPDATE:
Please keep in mind that IDataAccessorModel can be used by any desired DataAccess type you wish to define.
SQLDataAccessor implements IDataAccessorModel<IPerson, IAccessType>, so it would work only if <I, T> were <IPerson, IAccessType>. There is no guarantee about that, since the method is generic and I and T could be any type, so the cast fails.
Of course, since you're checking the types of I and T, you know the cast would be valid, but the compiler doesn't. You can trick it like this:
return (IDataAccessorModel<I, T>)(object)accessor;
However, since T has to be SqlServer, it doesn't make sense to make it a generic type parameter. And since I has to implement IPerson, there should be a constraint on it. So the method signature should be:
public IDataAccessor<I, T> Create<T>() where T : IPerson
It work for me if I declare SQLDataAccessor like this:
public class SQLDataAccessor : IDataAccessorModel<IPerson, SqlServer>
{
...
}
You are probably calling it like this
var factory = new FactoryDataAccess();
var da = factory.Create<IPerson, SqlServer>();
i.e. you call it with T being SqlServer. If you declare T as IAccessType in SQLDataAccessor it is not guaranteed that IAccessType would be SqlServer. Therefore the casting error. (However, SqlServer is guaranteed to be IAccessType as it probably implements it.)
SQLDataAccessor is not a generic class, but implements IDataAccessorModel<IPerson, IAccessType> exactly, so your method Create should return IDataAccessor<IPerson, IAccessType>, but you probably called it with other generic types.
Change SqlDataAccessor to:
public class SQLDataAccessor<I, T> : IDataAccessorModel<I, T>
{
internal SQLDataAccessor(IResult<string> result)
{
_connectionString = "";
_result = result;
}
private readonly string _connectionString;
private IResult<string> _result;
public T AccessType { get { return new SqlServer(); } }
public I Instance { get; private set; }
public IResult<string> Add(I instance)
{
Instance = instance;
return _result;
}
public IResult<string> Get(I instance)
{
Instance = instance;
return _result;
}
public IResult<string> Delete(I instance)
{
Instance = instance;
return _result;
}
public IResult<string> Update(I instance)
{
Instance = instance;
return _result;
}
}
You might want to limit I and T to the interfaces, so add a where constraint:
public class SQLDataAccessor<I, T> : IDataAccessorModel<I, T>
where I : IPerson
where T : IAccessType
The way you have it, I could be any type derived from IPerson and T is exactly of type SqlServer, which would cause the cast to fail since SQLDataAccessor implements the IDataAccessorModel with different parameters. You would need to have a more exact cast, such as:
return (IDataAccessorModel<IPerson, IAccessType>)accessor;