I have following parent class:
public class BaseType
{
public abstract Dictionary<string, object> dict { get; set; }
}
Child class:
public override Dictionary<string, object> dict
{
get
{
return fn();
}
set
{
//set dictionary[key]=value }
}
fn is implemented in child class as:
public static Dictionary<string, object> fn()
{
Dictionary<string, object> dictionary = new Dictionary<string, object>();
dictionary.Add("key1", "0");
dictionary.Add("key2", "something");
return dictionary;
}
I need to access this dictionary as follows:
BaseType test=new Child();
test.dict["key1"]=1;//set property
object strGet= test.dict["key2];//get property
How can I achieve the above get and set?
Your parent class is already invalid. You cannot have a property that takes arguments.
You can only expose the dictionary as a property itself. Note that you also need to make the class abstract as well:
public abstract class BaseType
{
public abstract Dictionary<string, object> Dict { get; set; }
}
Then, in subtypes of that class, you can set up the getter and setter so it returns a custom dictionary:
public class MyType : BaseType
{
public override Dictionary<string, object> Dict
{
get
{
return GetSomeDictionary();
}
set
{
DoSomethingWith(value);
}
}
}
Note, that this does not allow you to overwrite the behavior when you do someObj.Dict["key"] = "foo". The item accessor is built into the dictionary type, and you cannot overwrite that from within your class.
What you could do is expose a IDictionary<string, object> instead and provide your own type that wraps a normal dictionary but exposes your desired behavior instead.
If the whole purpose of your code is just to provide some default value for the dictionary, then you can solve this a lot easier:
public class MyType : BaseType
{
private Dictionary<string, object> _dict = null;
public override Dictionary<string, object> Dict
{
get
{
if (_dict == null)
{
_dict = InitializeDictionary();
}
return _dict;
}
set
{
_dict = value;
}
}
}
Where InitializeDictionary() returns a new dictionary with the default values.
I got it!! This way we can dynamically set the value of any key in dictionary.
public object objValue;
public string strKey;
public override Dictionary<string, object> dictionary
{
get
{
return fn();
}
set
{
setTest(strKey,objValue);
}
}
public void setTest(string strKey, object objValue)
{
dictionary[strKey] = objValue;
}
Related
In my application users can search for different things in various places. The same search code could be used for different things. I'm trying to create a cache in order to avoid querying the database every time.
// CustomerViewModel.cs
public async Task<Customer> SearchCustomerAsync(string searchCode)
{
if (Cache.GetOrDefault<Customer>(searchCode) is Customer c)
{
return c;
}
var customer = await GetCustomerFromDatabaseAsync(searchCode);
Cache.AddOrReplace(searchCode, customer);
return customer;
}
// SupplierViewModel.cs
public async Task<Supplier> SearchSupplierAsync(string searchCode)
{
if (Cache.GetOrDefault<Supplier>(searchCode) is Supplier s)
{
return s;
}
var supplier = await GetSupplierFromDatabaseAsync(searchCode);
Cache.AddOrReplace(searchCode, supplier);
return supplier;
}
Here is my cache implementation
public static class Cache
{
private static readonly Dictionary<Type, Dictionary<string, object>> _dictionary =
new Dictionary<Type, Dictionary<string, object>>();
public static void AddOrReplace<T>(string key, T value) where T : class
{
Type t = typeof(T);
if (!_dictionary.ContainsKey(t)) _dictionary.Add(t, new Dictionary<string, object>());
var cache = _dictionary[t];
if (cache.ContainsKey(key)) cache.Remove(key);
cache.Add(key, value);
}
public static T GetOrDefault<T>(string key) where T : class
{
Type t = typeof(T);
if (!_dictionary.ContainsKey(t)) return default;
var cache = _dictionary[t];
if (!cache.ContainsKey(key)) return default;
// Have to explicitly cast the object to T
return (T)cache[key];
}
}
The thing that bothers me is the inner dictionary being Dictionary<string, object>. For a given type, say Customer, I know that the inner dictionary will only ever contains customers, and should be Dictionary<string, Customer>.
Is there a way to have the inner dictionary strongly typed?
If not, would a Dictionary<string, Dictionary<Type, object>> be better suited? So I would check whether or not I've got something cached for the search code, and if so something cached for the given type.
I'm open to all suggestions, so if you think my approach is bad and I shouldn't even use a dictionary in the first place I'm all ears.
UPDATE:
As pointed out, given I'm only caching reference types I shouldn't be too worried about dealing with objects, since I won't be boxing value types. I've replaced the nested dictionaries with a Dictionary<(string, Type), object>.
public static class Cache
{
private static readonly Dictionary<(string, Type), object> _dictionary =
new Dictionary<(string, Type), object>();
public static void AddOrReplace<T>(string key, T value) where T : class
{
var typedKey = (key, typeof(T));
if (_dictionary.ContainsKey(typedKey)) _dictionary.Remove(typedKey);
_dictionary.Add(typedKey, value);
}
public static T GetOrDefault<T>(string key) where T : class
{
var typedKey = (key, typeof(T));
if (!_dictionary.TryGetValue(typedKey, out object value)) return default;
return (T)value;
}
}
I am working on a WFP application which contains a dynamic grid depending on the order type in question. Therefore I have bound the grid to a Dictionary<string, object>.
However on one screen where I allow users to paste in new orders, I noticed that sometimes not all values are persisted, typically when they paste in a large number, say 500 rows. I suspect this is because I am using Dictionary rather than ConcurrentDictionary so not all writes to the Dictionary are being persisted.
Order Object:
public interface IOrder : IDictionary<string, object>,
{
IOrderDataDictionary<string, object> OrderData { get; set; }
}
OrderDataDictionary
public class OrderDataDictionary<TKey, TValue> : IOrderDataDictionary<TKey, TValue>
{
private static readonly ILog Log = LogManager.GetLogger(typeof(OrderDataDictionary<TKey, TValue>));
private readonly IDictionary<TKey, TValue> _innerDictionary;
#region Constructors
public OrderDataDictionary()
{
_innerDictionary = new Dictionary<TKey, TValue>();
}
public OrderDataDictionary(int capacity)
{
_innerDictionary = new Dictionary<TKey, TValue>(capacity);
}
public OrderDataDictionary(IDictionary<TKey, TValue> dictionary)
{
_innerDictionary = new Dictionary<TKey, TValue>(dictionary);
}
...
}
Adding to Dictionary:
public Order ParseRows(List<string> rawRow, OrderType orderType)
{
Order order = GenerateOrderEntryRow(orderType);
List<string> row = rawRow.Select(x => x.ToString()).ToList();
foreach (BulkEntryColumnConfig column in _pasteHeader[orderType])
{
if (!column.IncludeInRequest || !column.AutoParse)
continue;
string rawVal = row[column.Index];
if (column.DataType == typeof (string))
{
Log.DebugFormat("{0}:{1}", column.Name, rawVal);
order.OrderData[column.Name] = rawVal;
}
}
...
return order;
}
Order
public Order()
{
_innerDictionary = new OrderDataDictionary<string, object>();
OrderData = _innerDictionary;
}
public Order(IDictionary<string, object> dictionary)
{
_innerDictionary = new OrderDataDictionary<string, object>(dictionary);
OrderData = _innerDictionary;
}
GenerateOrderEntryRow()
public Order GenerateOrderRow(OrderType orderType)
{
Dictionary<string, object> dict = new Dictionary<string, object>();
foreach (KeyValuePair<string, string> col in _columnDefinition[orderType])
{
dict.Add(col.Key, null);
}
dict["OrderType"] = orderType.ToString();
Order row = new Order(dict);
return row;
}
Calling ParseRows()
return Task<IList<Order>>.Factory.StartNew(() => {...ParseRows()...}
The key line is order.OrderData[column.Name] = rawVal; where I am adding a value to the dictionary using the indexer.
I'm never calling Order() which would mean a potential resizing of the underlying dictionary later. I only call Order(IDictionary dictionary) from GenerateOrderEntryRow() so not unless it is being invoked somewhere else implicitly.
My question is, why are not all values stored correctly, and should I modify Order.OrderData to be of type ConcurrentDictionary? Would this solve the problem of some writes being missed?
I've been researching a bit about reflections in C # and would like to know if I use a dictionary with keys-values can create an object with the variable with the name of each key in the dictionary and their values, the key value of that dictionary.
I have a method that does the opposite, that extracts an object from a dictionary, this dictionary contains the keys and the class properties and their values, the value of the properties.
I wonder how to do this if possible.
Below is my method, which extracts a dictionary of an object:
protected Dictionary<String, String> getObjectProperty(object objeto)
{
Dictionary<String, String> dictionary = new Dictionary<String, String>();
Type type = objeto.GetType();
FieldInfo[] field = type.GetFields();
PropertyInfo[] myPropertyInfo = type.GetProperties();
String value = null;
foreach (var propertyInfo in myPropertyInfo)
{
if (propertyInfo.GetIndexParameters().Length == 0)
{
value = (string)propertyInfo.GetValue(objeto, null);
value = value == null ? null : value;
dictionary.Add(propertyInfo.Name.ToString(), value);
}
}
return dictionary;
}
If you've already got a dictionary, I'd avoid reflection and just use DynamicObject
For example:
public class DynamicDictionary : DynamicObject
{
private readonly Dictionary<string, object> dictionary;
public DynamicDictionary(Dictionary<string, object> dictionary)
{
this.dictionary = dictionary;
}
public override bool TryGetMember(
GetMemberBinder binder, out object result)
{
return dictionary.TryGetValue(binder.Name, out result);
}
public override bool TrySetMember(
SetMemberBinder binder, object value)
{
dictionary[binder.Name] = value;
return true;
}
}
Which can be used as follows:
dynamic x = new DynamicDictionary(
new Dictionary<string, object> {{"Name", "Peter"}});
Console.WriteLine(x.Name);
I am not sure if this is what you're looking for, but judging by your question, I think you want to
instantiate types at run time from the types located in a dictionary, which will be obtained by providing a key.
If that is so, then you can create the following class which will hold key-value pairs of strings which will be your keys, and Types which will represent your values which will be instantiated.
class DictionaryActivator
{
Dictionary<string, Type> Dictionary = new Dictionary<string, Type>();
public DictionaryActivator()
{
Dictionary.Add("MyCar", typeof(Car));
Dictionary.Add("MyHouse", typeof(House));
Dictionary.Add("MyFruit", typeof(Fruit));
Dictionary.Add("MyComputer", typeof(Computer));
}
public T GetInstance<T>(string type, params object[] parameters)
{
if (parameters.Count() == 0)
{
return (T)Activator.CreateInstance(Dictionary[type]);
}
else
{
return (T)Activator.CreateInstance(Dictionary[type], parameters.ToArray());
}
}
}
You can also create four test classes to test this setup.
class House
{
public int Number = 25;
}
class Car
{
public double Price = 50000;
}
class Fruit
{
public string Name = "Apple";
}
class Computer
{
public string Cpu { get; set; }
public string Gpu { get; set; }
public Computer(string cpu, string gpu)
{
Cpu = cpu;
Gpu = gpu;
}
}
Once this is done, you can run the following lines of code to get all the types from the dictionary, instantiate them and cast them to appropriate types. As you might notice, the last Computer example is showing you how to add multiple parameters (in this case two) to the newly created instance and return it as an instance of type object.
In the end you can cast it to the Computer type so you can check that the constructor parameters actually went to the corresponding properties.
class Program
{
static void Main()
{
var source = new DictionaryActivator();
Console.WriteLine(source.GetInstance<Car>("MyCar").Price);
Console.WriteLine(source.GetInstance<House>("MyHouse").Number);
Console.WriteLine(source.GetInstance<Fruit>("MyFruit").Name);
var computer = source.GetInstance<object>("MyComputer", "Fast CPU", "Fast GPU");
Console.WriteLine((computer as Computer).Cpu);
Console.WriteLine((computer as Computer).Gpu);
Console.Read();
}
}
Since ExpandoObject is a dictionary, you can use this extension function:
public static object With(this IDictionary<string, object> obj, IDictionary<string,object> additionalProperties)
{
foreach (var name in additionalProperties.Keys)
obj[name] = additionalProperties[name];
return obj;
}
Usage:
var dynamicObj = new System.Dynamic.ExpandoObject().With(myDictionary);
I have a class that defines a protected field. The protected field has a field initializer.
When I deserialize the concrete class, the field initializer is not run. Why? What is the best pattern to solve the problem? If I move the initialization into a constructor, the constructor is also not invoked.
[DataContract]
public class MyConcrete
{
// FIELD INITIALIZER DOES NOT RUN WHEN COMMENTED IN:
protected readonly Dictionary<int, string> myDict;// = new Dictionary<int, string>();
public MyConcrete()
{
myDict = new Dictionary<int, string>();
}
private bool MyMethod(int key)
{
return myDict.ContainsKey(key);
}
private int myProp;
[DataMember]
public int MyProp
{
get { return myProp; }
set { bool b = MyMethod(value); myProp = value; } // Call MyMethod to provoke error
}
}
ORIGINAL CLASS HIERARCHY
[DataContract]
public abstract class MyAbstract
{
// THIS INITIALIZER IS NOT RUN WHILE DESERIALIZING:
protected readonly Dictionary<int, string> myDict = new Dictionary<int, string>();
private bool MyMethod(int key)
{
return myDict.ContainsKey(key);
}
private int myProp;
[DataMember]
public int MyProp
{
get { return myProp; }
set { bool b = MyMethod(value); myProp = value; } // Call MyMethod to provoke error
}
}
[DataContract]
public class MyConcrete : MyAbstract
{
}
class Program
{
static void Main(string[] args)
{
string tempfn = Path.GetTempFileName();
MyConcrete concrete = new MyConcrete() { MyProp = 42 };
string data = concrete.SerializeToString<MyConcrete>();
MyConcrete rehydrated = SerializationHelper.DeserializeFromString<MyConcrete>(data);
}
}
SUPPORTING METHODS
static public string SerializeToString<T>(this T obj)
{
return SerializationHelper.SerializeToString<T>(obj);
}
static public string SerializeToString<T>(T obj)
{
DataContractSerializer s = new DataContractSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream())
{
s.WriteObject(ms, obj);
ms.Position = 0;
using (StreamReader sr = new StreamReader(ms))
{
string serialized = sr.ReadToEnd();
return serialized;
}
}
}
static public T DeserializeFromString<T>(string serializedDataAsString)
{
DataContractSerializer s = new DataContractSerializer(typeof(T));
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(serializedDataAsString)))
{
object s2 = s.ReadObject(ms);
return (T)s2;
}
}
On deserialization neither the constructors nor the field initializers are called and a "blank" un-initialized object is used instead.
To resolve it you can make use of the OnDeserializing or OnDerserialized attributes to have the deserializer call a function with the following signature:
void OnDeserializing(System.Runtime.Serialization.StreamingContext c);
In that function is where you can initialize whatever was missed within the deserialization process.
In terms of convention, I tend to have my constructor call a method OnCreated() and then also have deserializating method call the same thing. You can then handle all of the field initialization in there and be sure it's fired before deserialization.
[DataContract]
public abstract class MyAbstract
{
protected Dictionary<int, string> myDict;
protected MyAbstract()
{
OnCreated();
}
private void OnCreated()
{
myDict = new Dictionary<int, string>();
}
[OnDeserializing]
private void OnDeserializing(StreamingContext c)
{
OnCreated();
}
private bool MyMethod(int key)
{
return myDict.ContainsKey(key);
}
private int myProp;
[DataMember]
public int MyProp
{
get { return myProp; }
set { bool b = MyMethod(value); myProp = value; }
}
}
Another approach is to access your field through a protected (in your example) property, and initialise the field using the null-coalescing (??) operator
protected Dictionary<int, string> myDict = new Dictionary<int, string>();
protected Dictionary<int, string> MyDict
{
get
{
return myDict ?? (myDict = new Dictionary<int, string>());
}
}
The downsides are that you lose the benefits of readonly, and need to make sure that you only access the value via the property.
I am trying to do the following but I think I must be missing something...(fairly new to generics)
(Need to target .NET 2.0 BTW)
interface IHasKey
{
string LookupKey { get; set; }
}
...
public static Dictionary<string, T> ConvertToDictionary(IList<T> myList) where T : IHasKey
{
Dictionary<string, T> dict = new Dictionary<string, T>();
foreach(T item in myList)
{
dict.Add(item.LookupKey, item);
}
return dict;
}
Unfortunately, this gives a "Constraints are not allowed on non-generic declarations" error. Any ideas?
You have not declared the generic parameter.
Change your declaration to:
public static Dictionary<string, T> ConvertToDictionary<T> (IList<T> myList) where T : IHasKey{
}
Try something like this
public class MyObject : IHasKey
{
public string LookupKey { get; set; }
}
public interface IHasKey
{
string LookupKey { get; set; }
}
public static Dictionary<string, T> ConvertToDictionary<T>(IList<T> myList) where T: IHasKey
{
Dictionary<string, T> dict = new Dictionary<string, T>();
foreach(T item in myList)
{
dict.Add(item.LookupKey, item);
}
return dict;
}
List<MyObject> list = new List<MyObject>();
MyObject o = new MyObject();
o.LookupKey = "TADA";
list.Add(o);
Dictionary<string, MyObject> dict = ConvertToDictionary(list);
You forgot the Generic Paramter in the method
public static Dictionary<string, T> ConvertToDictionary<T>(IList<T> myList) where T: IHasKey
Since the classes in the input list are different (as you say in your comment) you can either implement it like suggested by #orsogufo, or you could just as well implement your signature on the interface itself:
public static Dictionary<string, IHasKey> ConvertToDictionary(IList<IHasKey> myList)
{
var dict = new Dictionary<string, IHasKey>();
foreach (IHasKey item in myList)
{
dict.Add(item.LookUpKey, item);
}
return dict;
}
Using the generic declaration is best if you have a list of one specific implementation of the interface as noted in the comments to the other answer.