Accessing a dictionary from a class dynamically without knowing its name
I have a class named SomeClass
. It contains several dictionaries.
public class SomeClass
{
public Dictionary<double, int[]> Dict1;
public Dictionary<double, int[]> Dict2;
public Dictionary<double, int[]> Dict3;
}
I find out the name of the dictionary at runtime. Means in which the dictionary I need to assign data is only known at runtime. I am getting the name of the dictionary string
dynamically. Something like -
String dictName = "Dict1"; //Achieved through some code mechanism in my project.
SomeClass DynValue = new SomeClass();
DynValue.[dictName/* Known at run time */].Add(3, new int[] { 5, 10 });
source to share
You must initialize the dictionaries after creating the object.
public class SomeClass
{
public Dictionary<double, int[]> Dict1 = new Dictionary<double, int[]>();
public Dictionary<double, int[]> Dict2 = new Dictionary<double, int[]>();
public Dictionary<double, int[]> Dict3 = new Dictionary<double, int[]>();
}
To dynamically change the field of an object using a name, you must use reflection:
String dictName = "Dict1"; //Achieved through some code mechanism in my project.
SomeClass obj = new SomeClass();
// Get dictionary interface object of 'Dict1' field using reflection
var targetDict = obj.GetType().GetField(dictName).GetValue(obj) as IDictionary;
// Add key and value to dictionary
targetDict.Add(3.5d, new int[] { 5, 10 });
If you need to initialize a dictionary using reflection, you should use this:
String dictName = "Dict1"; //Achieved through some code mechanism in my project.
SomeClass obj = new SomeClass();
// Get field info by name
var dictField = obj.GetType().GetField(dictName);
// Get dictionary interface object from field info using reflection
var targetDict = dictField.GetValue(obj) as IDictionary;
if (targetDict == null) // If field not initialized
{
// Initialize field using default dictionary constructor
targetDict = dictField.FieldType.GetConstructor(new Type[0]).Invoke(new object[0]) as IDictionary;
// Set new dictionary instance to 'Dict1' field
dictField.SetValue(obj, targetDict);
}
targetDict.Add(3.5d, new int[] { 5, 10 });
source to share
I agree that this is nice.
If a population with a lot of elements is possible in loops, the reflection might not be the same as the performer. Only profiling will be shown.
If you have a small (or fixed) number of internal dictionaries, may I suggest moving on to something like below. I used nameof to make the safe code below.
class SomeClass
{
private readonly Dictionary<double, int[]> Dict1 = new Dictionary<double, int[]>();
private readonly Dictionary<double, int[]> Dict2 = new Dictionary<double, int[]>();
private readonly Dictionary<double, int[]> Dict3 = new Dictionary<double, int[]>();
public Dictionary<double, int[]> this[string index]
{
get
{
switch(index)
{
case nameof(Dict1)) return Dict1;
case nameof(Dict2)) return Dict2;
case nameof(Dict3)) return Dict3;
default:
throw new KeyNotFoundException(index);
}
}
}
public static void Main(string[] args)
{
var c = new SomeClass();
c["Dict1"].Add(42.0, new [100, 200]);
c["Dict20"].Add(43.0, new [102, 203]); // KeyNotFoundException("Dict20")
}
}
source to share