I have implemented a very simple object cache in C# using AppDomain SetData() and GetData() like this (to reduce the number of DB calls for data that changes infrequently):
class Program
{
static void Main(string[] args)
{
List<string> users = (List<string>)GetUserList();
Console.ReadKey();
}
private static object GetUserList()
{
var users = AppDomain.CurrentDomain.GetData("GetUserList");
if (null == users)
{
users = new List<string>() { "apple", "banana" }; // dummy db results
AppDomain.CurrentDomain.SetData("GetUserList", users);
}
return users;
}
}
I now want to implement a simple PurgeCache() method iterate through the keys in my CurrentDomain and set the value to null.
How can I go about doing this?
EDIT
Based on Knaģis's reply, I have come up with the following.
ObjectCache.cs
class ObjectCache
{
private const string CacheName = "ObjectCache";
private static Dictionary<String, Object> Load()
{
Dictionary<string, object> myObjectCache = AppDomain.CurrentDomain.GetData(CacheName) as Dictionary<string, object>;
if (null == myObjectCache)
{
myObjectCache = new Dictionary<string, object>();
AppDomain.CurrentDomain.SetData(CacheName, myObjectCache);
}
return myObjectCache;
}
private static void Save(Object myObjectCache)
{
AppDomain.CurrentDomain.SetData(CacheName, myObjectCache);
}
public static void Purge()
{
Dictionary<string, object> myObjectCache = ObjectCache.Load();
myObjectCache.Clear();
ObjectCache.Save(myObjectCache);
}
public static void SetValue(String myKey, Object myValue)
{
Dictionary<string, object> myObjectCache = ObjectCache.Load();
myObjectCache[myKey] = myValue;
ObjectCache.Save(myObjectCache);
}
public static Object GetValue(String myKey)
{
Dictionary<string, object> myObjectCache = ObjectCache.Load();
return myObjectCache.ContainsKey(myKey) ? myObjectCache[myKey] : null;
}
}
Program.cs - Usage
class Program
{
static void Main(string[] args)
{
List<string> users = GetUserList<List<string>>();
ObjectCache.Purge(); // Removes Cache
Console.ReadKey();
}
private static T GetUserList<T>()
{
var users = ObjectCache.GetValue("GetUserList");
if (null == users) // No Cache
{
users = new List<string>() { "adam", "smith" }; // Dummy DB Results
ObjectCache.SetValue("GetUserList", users);
}
return (T)users;
}
}
AppDomain.GetData should not be used for caching purposes. Instead use solutions like System.Runtime.Caching. Or even just a static ConcurrentDictionary will be better.
If you insist on using AppDomain to store the values you should never delete everything in it - it stores information required by .NET framework to run properly.
Either store your values in a dictionary inside the AppDomain object or keep a list of keys yourself.
A simple in memory cache using a static dictionary (the second approach is for .NET 2.0 with explicit locks - note that this is very simple solution, there are better alternatives to locking):
using System;
using System.Collections.Concurrent;
namespace YourNamespace
{
public static class ObjectCache
{
private readonly static ConcurrentDictionary<string, object> Data = new ConcurrentDictionary<string, object>();
public static void SetValue(string key, object value)
{
Data[key] = value;
}
public static object GetValue(string key)
{
object t;
if (!Data.TryGetValue(key, out t))
return null;
return t;
}
public static void Purge()
{
Data.Clear();
}
}
public static class ObjectCache2
{
private readonly static Dictionary<string, object> Data = new Dictionary<string, object>();
public static void SetValue(string key, object value)
{
lock (Data)
Data[key] = value;
}
public static object GetValue(string key)
{
object t;
lock (Data)
{
if (!Data.TryGetValue(key, out t))
return null;
}
return t;
}
public static void Purge()
{
lock (Data)
Data.Clear();
}
}
}
Related
I have a config with thousands of EnumValues and I parse them in runtime
void DoSmth()
{
foreach (var line in configLines)
{
var myEnumValue = (MyEnum) Enum.Parse(line);
...
}
}
and I can improve perfomance by creating a map between a string from the config and an actual enumValue
Dictionary<string, MyEnum> dict = new();
void DoSmth()
{
foreach (var line in configLines)
{
if (!dict.ContainsKey(line)
dict.Add(line, (MyEnum) Enum.Parse(typeof(MyEnum), line));
var myEnumValue = dict[line];
...
}
}
Q:
Is there any way (maybe using some co/contravariance magic) to create a generic function so it could create such dictionaries dynamically to avoid writing the same caching code over and over again?
e.g.
void DoSmth()
{
foreach (var line in configLines)
{
var myEnumValue = MyExtensions.Parse<MyEnum>(line);
...
}
}
class MyExtensions
{
Dictionary<Type, Dictionary<string, EnumValue> _cachedEnumValues; // < EnumValue type not exists, so how to?
public T Parse<T>(string s) where T : Enum
{
if (!_cachedEnumValues.ContansKey(typeof(T))
_cachedEnumValues.Add(typeof(T), new Dictionary<string, T>();
if (!_cachedEnumValues[typeof(T)].ContansKey(s))
_cachedEnumValues[typeof(T)].Add(s, (MyEnum) Enum.Parse(typeof(MyEnum), s);
return _cachedEnumValues[typeof(T)][s];
}
}
Sure:
public sealed class EnumHelper<T> where T : Enum
{
private static readonly ConcurrentDictionary<string, T> Cache = new ConcurrentDictionary<string, T>(StringComparer.OrdinalIgnoreCase);
public static T Parse(string s)
{
return Cache.GetOrAdd(s, k => (T)Enum.Parse(typeof(T), k));
}
}
Usage:
var t = EnumHelper<SearchOption>.Parse(SearchOption.AllDirectories.ToString());
I'd like to expose a type safe API over a particular JSON format. Here is basically what I have so far:
public class JsonDictionary
{
Dictionary<string, Type> _keyTypes = new Dictionary<string, Type> {
{ "FOO", typeof(int) },
{ "BAR", typeof(string) },
};
IDictionary<string, object> _data;
public JsonDictionary()
{
_data = new Dictionary<string, object>();
}
public void Set<T>(string key, T obj)
{
if (typeof(T) != _keyTypes[key])
throw new Exception($"Invalid type: {typeof(T)} vs {_keyTypes[key]}");
_data[key] = obj;
}
public dynamic Get(string key)
{
var value = _data[key];
if (value.GetType() != _keyTypes[key])
throw new Exception($"Invalid type: {value.GetType()} vs {_keyTypes[key]}");
return value;
}
}
Which can be used nicely as:
JsonDictionary d = new JsonDictionary();
d.Set("FOO", 42);
d.Set("BAR", "value");
However reading the value is a little disapointing and rely on late binding:
var i = d.Get("FOO");
var s = d.Get("BAR");
Assert.Equal(42, i);
Assert.Equal("value", s);
Is there some C# magic that I can use to implement a type-safe generic Get<T> instead of relying on dynamic here (ideally type should be checked at compilation time) ? I'd like to also use the pattern for Set<T> so that d.Set("BAR", 56); triggers a compilation warning.
Dictionary<string, Type> _keyTypes can be made static if needed. The above is just work in progress.
I was using solution similar to this:
public class JsonDictionary
{
public static readonly Key<int> Foo = new Key<int> { Name = "FOO" };
public static readonly Key<string> Bar = new Key<string> { Name = "BAR" };
IDictionary<string, object> _data;
public JsonDictionary()
{
_data = new Dictionary<string, object>();
}
public void Set<T>(Key<T> key, T obj)
{
_data[key.Name] = obj;
}
public T Get<T>(Key<T> key)
{
return (T)_data[key.Name];
}
public sealed class Key<T>
{
public string Name { get; init; }
}
}
I would convert T to object and check object type with .GetType()
public class JsonDictionary
{
Dictionary<string, Type> _keyTypes = new Dictionary<string, Type> {
{ "FOO", typeof(int) },
{ "BAR", typeof(string) },
};
IDictionary<string, object> _data;
public JsonDictionary()
{
_data = new Dictionary<string, object>();
}
public void Set(string key, object obj)
{
if (obj.GetType() != _keyTypes[key])
throw new Exception($"Invalid type: {obj.GetType()} vs {_keyTypes[key]}");
_data[key] = obj;
}
public object Get(string key)
{
return _data[key];
}
}
I tried it like this and it worked:
JsonDictionary d = new JsonDictionary();
d.Set("FOO", 42);
d.Set("BAR", "value");
var i = d.Get("FOO");
var s = d.Get("BAR");
Console.WriteLine(i);
Console.WriteLine(s);
But to be honest, I don't like what you are trying to achieve.
I have some already defined extension method like this:
public static object Get(this IDictionary<string, object> dict, string key)
{
if (dict.TryGetValue(key, out object value))
{
return value;
}
return null;
}
but if I try to use it with an instance of an
IDictionary <string, myClass>
it won't show up. I thought every class derived from object. Questions:
1) Why is this happening?
2) How could I make an extension method that includes all kinds of IDictionary?
This is perfectly working:
using System.Collections.Generic;
namespace ConsoleApp1
{
public class Program
{
public static void Main(string[] args)
{
var dic = new Dictionary<string, object> {{"Test", 1}};
var result = dic.Get("Test");
}
}
public static class MyExtensions
{
public static object Get(this IDictionary<string, object> dict, string key)
{
if (dict.TryGetValue(key, out object value))
{
return value;
}
return null;
}
public static T Get<T>(this IDictionary<string, T> dict, string key)
{
if (dict.TryGetValue(key, out T value))
{
return value;
}
return default(T);
}
}
}
I'm trying to use a dictionary as a class member. I want to
use a property to get/set the key/value of the dictionary but I'm
confused as how to use a dictionary as a property. Since there are 2
parts, I don't know how to setup the get/sets.
You could try this:
class Example {
private Dictionary<int,string> _map;
public Dictionary<int,string> Map { get { return _map; } }
public Example() { _map = new Dictionary<int,string>(); }
}
Implementation would go along the lines of:
var e = new Example();
e.Map[42] = "The Answer";
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
Console.WriteLine("Hello World");
var cl = new cl();
populate(cl.dict);
foreach(var d in cl.dict)
Console.WriteLine(d.Key);
}
private static void populate(Dictionary<int, string> d)
{
for (int i = 0; i < 10 ; i++)
{
if (!d.ContainsKey(i))
{
d.Add(i, i.ToString());
}
}
}
}
public class cl
{
public Dictionary<int, string> dict;
public cl()
{
dict = new Dictionary<int, string>();
}
}
Do you mean this ?
class MyDictionary<TKey, TValue>
{
private readonly Dictionary<TKey, TValue> _dictionary;
public void Add(TKey key, TValue value)
{
_dictionary.Add(key, value);
}
public void Clear()
{
_dictionary.Clear();
}
public bool Remve(TKey key)
{
return _dictionary.Remove(key);
}
.... and other methods...
public MyDictionary(Dictionary<TKey, TValue> dictionary)
{
_dictionary = dictionary;
}
}
I have created an architecture in my C# code which does exactly what I want, but seems it would be very difficult to maintain in the long-run and am hoping there's a design pattern / better architecture I could be pointed towards.
I have created an object Test which, again, does exactly what I need perfectly which has the following structure:
class Test
{
public static Dictionary<string, Func<Test, object>> MethodDictionary;
public double Var1;
public double Var2;
private Lazy<object> _test1;
public object Test1 { get { return _test1.Value; } }
private Lazy<object> _test2;
public object Test2 { get { return _test2.Value; } }
public Test()
{
_test1 = new Lazy<object>(() => MethodDictionary["Test1"](this), true);
_test2 = new Lazy<object>(() => MethodDictionary["Test2"](this), true);
}
}
What this allows me to do is, at run-time to assign a dictionary of functions to my Test object and the 2 properties Test1 & Test2 will use the functions loaded into it to return values.
The implementation looking somewhat as follows:
class Program
{
static void Main(string[] args)
{
Dictionary<string, Func<Test, object>> MethodDictionary = new Dictionary<string,Func<Test,object>>();
MethodDictionary.Add("Test1", TestMethod1);
MethodDictionary.Add("Test2", TestMethod2);
Test.MethodDictionary = MethodDictionary;
var x = new Test() { Var1 = 20, Var2 = 30 };
Console.WriteLine(x.Test1.ToString());
Console.WriteLine(x.Test2.ToString());
Console.ReadKey();
}
private static object TestMethod1(Test t)
{ return t.Var1 + t.Var2; }
private static object TestMethod2(Test t)
{ return t.Var1 - t.Var2; }
}
And it works great and has proven very efficient for large sets of Test objects.
My challenge is that if I ever want to add in a new method to my Test class, I need to add in the:
private Lazy<object> _myNewMethod;
public object MyNewMethod { get { return _myNewMethod.Value; } }
Update the constuctor with the key to look for in the dictionary
And, although that is pretty simple, I'd love to have a 1-line add-in (maybe some form of custom object) or have the properties read directly form the dictionary without any need for defining them at all.
Any ideas? ANY help would be great!!!
Thanks!!!
One of the ways in which you could achieve your desired behavior, is to use something that resembles a miniature IoC framework for field injection, tuned to your specific use case.
To make things easier, allow less typing in your concrete classes and make things type-safe, we introduce the LazyField type:
public class LazyField<T>
{
private static readonly Lazy<T> Default = new Lazy<T>();
private readonly Lazy<T> _lazy;
public LazyField() : this(Default) { }
public LazyField(Lazy<T> lazy)
{
_lazy = lazy;
}
public override string ToString()
{
return _lazy.Value.ToString();
}
public static implicit operator T(LazyField<T> instance)
{
return instance._lazy.Value;
}
}
Furthermore, we define an abstract base class, that ensures that these fields will be created at construction time:
public abstract class AbstractLazyFieldHolder
{
protected AbstractLazyFieldHolder()
{
LazyFields.BuildUp(this); // ensures fields are populated.
}
}
Skipping for a moment how this is achieved (explained further below), this allows the following way of defining your Test class:
public class Test : AbstractLazyFieldHolder
{
public double Var1;
public double Var2;
public readonly LazyField<double> Test1;
public readonly LazyField<double> Test2;
}
Note that these fields are immutable, initialized in the constructor. Now, for your usage example, the below snippet shows the "new way" of doing this:
LazyFields.Configure<Test>()
// We can use a type-safe lambda
.SetProvider(x => x.Test1, inst => inst.Var1 + inst.Var2)
// Or the field name.
.SetProvider("Test2", TestMethod2);
var x = new Test() { Var1 = 20, Var2 = 30 };
Console.WriteLine(x.Test1);
double test2Val = x.Test2; // type-safe conversion
Console.WriteLine(test2Val);
// Output:
// 50
// -10
The class below provides the services that support the configuration and injection of these field value.
public static class LazyFields
{
private static readonly ConcurrentDictionary<Type, IBuildUp> _registry = new ConcurrentDictionary<Type,IBuildUp>();
public interface IConfigureType<T> where T : class
{
IConfigureType<T> SetProvider<FT>(string fieldName, Func<T, FT> provider);
IConfigureType<T> SetProvider<F, FT>(Expression<Func<T, F>> fieldExpression, Func<T, FT> provider) where F : LazyField<FT>;
}
public static void BuildUp(object instance)
{
System.Diagnostics.Debug.Assert(instance != null);
var builder = _registry.GetOrAdd(instance.GetType(), BuildInitializer);
builder.BuildUp(instance);
}
public static IConfigureType<T> Configure<T>() where T : class
{
return (IConfigureType<T>)_registry.GetOrAdd(typeof(T), BuildInitializer);
}
private interface IBuildUp
{
void BuildUp(object instance);
}
private class TypeCfg<T> : IBuildUp, IConfigureType<T> where T : class
{
private readonly List<FieldInfo> _fields;
private readonly Dictionary<string, Action<T>> _initializers;
public TypeCfg()
{
_fields = typeof(T)
.GetFields(BindingFlags.Instance | BindingFlags.Public)
.Where(IsLazyField)
.ToList();
_initializers = _fields.ToDictionary(x => x.Name, BuildDefaultSetter);
}
public IConfigureType<T> SetProvider<FT>(string fieldName, Func<T,FT> provider)
{
var pi = _fields.First(x => x.Name == fieldName);
_initializers[fieldName] = BuildSetter<FT>(pi, provider);
return this;
}
public IConfigureType<T> SetProvider<F,FT>(Expression<Func<T,F>> fieldExpression, Func<T,FT> provider)
where F : LazyField<FT>
{
return SetProvider((fieldExpression.Body as MemberExpression).Member.Name, provider);
}
public void BuildUp(object instance)
{
var typedInstance = (T)instance;
foreach (var initializer in _initializers.Values)
initializer(typedInstance);
}
private bool IsLazyField(FieldInfo fi)
{
return fi.FieldType.IsGenericType && fi.FieldType.GetGenericTypeDefinition() == typeof(LazyField<>);
}
private Action<T> BuildDefaultSetter(FieldInfo fi)
{
var itemType = fi.FieldType.GetGenericArguments()[0];
var defValue = Activator.CreateInstance(typeof(LazyField<>).MakeGenericType(itemType));
return (inst) => fi.SetValue(inst, defValue);
}
private Action<T> BuildSetter<FT>(FieldInfo fi, Func<T, FT> provider)
{
return (inst) => fi.SetValue(inst, new LazyField<FT>(new Lazy<FT>(() => provider(inst))));
}
}
private static IBuildUp BuildInitializer(Type targetType)
{
return (IBuildUp)Activator.CreateInstance(typeof(TypeCfg<>).MakeGenericType(targetType));
}
}
Look at library https://github.com/ekonbenefits/impromptu-interface.
With it and using DynamicObject i wrote sample code that shows how to simplify adding new methods:
public class Methods
{
public Methods()
{
MethodDictionary = new Dictionary<string, Func<ITest, object>>();
LazyObjects = new Dictionary<string, Lazy<object>>();
}
public Dictionary<string, Func<ITest, object>> MethodDictionary { get; private set; }
public Dictionary<string, Lazy<object>> LazyObjects { get; private set; }
}
public class Proxy : DynamicObject
{
Methods _methods;
public Proxy()
{
_methods = new Methods();
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = _methods.LazyObjects[binder.Name].Value;
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
_methods.MethodDictionary[binder.Name] = (Func<ITest, object>)value;
_methods.LazyObjects[binder.Name] = new Lazy<object>(() => _methods.MethodDictionary[binder.Name](this.ActLike<ITest>()), true);
return true;
}
}
//now you can add new methods by add single method to interface
public interface ITest
{
object Test1 { get; set; }
object Test2 { get; set; }
}
class Program
{
static void Main(string[] args)
{
var x = new Proxy().ActLike<ITest>();
x.Test1 = new Func<ITest, object>((y) => "Test1");
x.Test2 = new Func<ITest, object>((y) => "Test2");
Console.WriteLine(x.Test1);
Console.WriteLine(x.Test2);
}
}
I don't know what you are trying to do, but I think you can use a simpler approach like this:
class Test
{
public static Dictionary<string, Func<Test, object>> MethodDictionary;
public double Var1;
public double Var2;
}
Calling the function is simple:
static void Main(string[] args)
{
Dictionary<string, Func<Test, object>> MethodDictionary = new Dictionary<string,Func<Test,object>>();
MethodDictionary.Add("Test1", TestMethod1);
MethodDictionary.Add("Test2", TestMethod2);
Test.MethodDictionary = MethodDictionary;
var x = new Test() { Var1 = 20, Var2 = 30 };
Console.WriteLine(Test.MethodDictionary["Test1"](x).ToString());
Console.WriteLine(Test.MethodDictionary["Test2"](x).ToString());
Console.ReadKey();
}