I have been working on some code that probe through the entries of a generic dictionary Dictionary<TKey, TValue>, using reflection. Unlike working with Hashtable, it's not easy to find out the entries' key and value information. Here is the code depict the problem.
Suppose I have a class hold two fields:
public class MyClass
{
Dictionary<string, DateTime> m_dateTimeDictionary;
Hashtable m_dateTimeHashTable;
}
I have an instance of the class and its type info:
…
MyClass myClass = new MyClass();
Type myType = myClass.GetType();
…
I have some code that probe through the reflection:
foreach (FieldInfo fi in myType.GetFields(BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly))
{
Type IEnumerableType = fi.FieldType.GetInterface("IEnumerable",
true);
if (IEnumerableType != null)
{
IEnumerable iEnum = (IEnumerable)fi.GetValue(myClass);
foreach (object de in iEnum)
{
…
}
}
}
I am interested to find out the information of variable de. For the Hashtable field m_dateTimeHashTable I can cast de to DictionaryEntry, then from DictionaryEntry I can get the key and value object. For the Dictionary field m_dateTimeDictionary the only type that I can cast de to is KeyValuePair<string, DateTime>. From the KeyValuePair I also have not problem to access the key and value. But the problem is during coding time I don't suppose to know the precise type of the entries. So, my question is without knowing the dictionary type, how to get the key and value object of each entry I thought about implement my probing code using generic. But it won't help if the client class that I am trying probe with has multiple fields of multiple dictionary types.
Anybody have don't this before Thanks!

How to get Dictionary<Tkey, TValue> entry information through reflection?
ArunBandy
ariana28
I am not going to answer your question directly; but challenge an assumption which may change your design or approach.
It is easy to access key value pairs and enumerate through a dictionary type object. Example:
Dictionary<string,string> genList = new Dictionary<string,string>();
genList.Add("Hello", "World");
genList.Add("Hash", "Table");
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<string, string> item in genList)
sb.AppendFormat("{0}\t{1}{2}",
item.Value,
item.Key,
System.Environment.NewLine);
Console.Write(sb.ToString()); // Outputs all string value pairs.
Hope this helps. Good luck.
SWhittet
Object o = <SomeKeyValuePairOfUnknowType>;
Type kvpType = o.GetType(); // the actual type of the KeyValuePair.
Type[] kvpArguments = kvpType.GetGenricArguments();
Type tKey = kvpArguments[0];
Type tValue = kvpArguments[1];
To create an object of tKey, tValue.
object CreateKeyValuePair(Type tKey, Type tValue)
{
Type kvpType = typeof(KeyValuePair<,>); // the unbound generic type.
Type boundKvp = kvpType.MakeGenericType(new Type[] { tKey, tValue });
// somebody else can explain how to construct an object from a boudn type.
// It can be done at runtime.
// I've seen it, just can't remember it off the top of my head.
}
BALA SINGAM
You are on the right track, but one level above. The crux of this issue revolves around what Dictionary.Enumerator.Current returns. That return is a KeyValuePair Generic Structure . Such a return is used in the foreach:
What these forum messages are trying to accomplish is how does one, via reflection dynamically define a kevalue pair; ie how does one replace the definition section as what is shown in red above in a dynamic fashion at runtime It seems only at compile time can one do that.
Robert Kozak
The whole point of using the generic collections is for strong typing. If you are using reflection to determine types at runtime then you are not using strong typing, so dont bother with the Dictionary<>; just use a hashtable.
Your approach seems to have some funamental problems with it. Can you explain what it is that your are trying to accomplish, and why you are using reflection to do it Maybe we can come up with a better solution.
mok
The following example is as close as I could get. The constraint is that you have to know ahead of time the type associated to the dictionary. If you know that, this turns into a switch statement:
Dictionary<string, string> genList = new Dictionary<string, string>();
genList.Add("Hello", "World");
genList.Add("Hash", "Table");
Type itsType = genList.GetType();
Console.WriteLine("Is this a generic type {0}", itsType.IsGenericType); // True
Console.WriteLine("Is this a generic type definition {0}", itsType.IsGenericTypeDefinition); // false
Type[] typeParameters = itsType.GetGenericArguments();
Console.WriteLine(" List {0} type arguments:", typeParameters.Length);
foreach (Type tParam in typeParameters)
Console.WriteLine(" Type argument: {0}", tParam);
if ((typeParameters[0] == typeof(string)) || (typeParameters[1] == typeof(string)))
{
IEnumerable intToDictionary = genList; // Cast to IEnumerable
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<string, string> item in intToDictionary)
sb.AppendFormat("{0}\t{1}{2}",
item.Value,
item.Key,
System.Environment.NewLine);
Console.WriteLine(sb.ToString());
}
output:
Is this a generic type definition False
List 2 type arguments:
Type argument: System.String
Type argument: System.String
World Hello
Table Hash
Tom Michaels
Check out the following members of the type class, they might point you in the right direction:
ContainsGenericParameters
GenericParameterAttributes
GenericParameterPosition
IsGenericParameter
IsGenericType
IsGenericTypeDefinition
GetGenericArguments
GetGenericParameterConstraints
GetGenericTypeDefinition
Using these member you should be able to query the instance of KeyValuePair that you get back to determine the types of its Key and Value properties
Seericssop
Patrick Sears
See my further explanation just posted. I see how your code works. But can you get the key and value of each entry without assume the type <string, string> For example, do some add after new Holder():
hl.Add(“key1”, “value1”);
…
Then in the main code can you get the keys and values back without assume you know the dictionary type Use reflection only.
PSRibeiro
Thanks! This is one step closer to my target. I don't know how many types will be involved in the dictionary.
yelhsawm
public class Holder
{
public Dictionary<string, string> abc = new Dictionary<string, string>();
}
class Progam
{
static void Main(string[] args)
{
Holder hl = new Holder();
FieldInfo[] myFieldInfo;
Type myType = typeof(Holder);
// Get the type and fields of FieldInfoClass.
myFieldInfo = myType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance| BindingFlags.Public);
Console.WriteLine("\nThe fields of " +"FieldInfoClass are \n");
// Display the field information of FieldInfoClass.
for (int i = 0; i < myFieldInfo.Length; i++)
{
Console.WriteLine("\nName : {0}", myFieldInfo[ i ].Name);
Console.WriteLine("Declaring Type : {0}", myFieldInfo[ i ].DeclaringType);
Console.WriteLine("IsPublic : {0}", myFieldInfo[ i ].IsPublic);
Console.WriteLine("MemberType : {0}", myFieldInfo[ i ].MemberType);
Console.WriteLine("FieldType : {0}", myFieldInfo[ i ].FieldType);
Console.WriteLine("IsFamily : {0}", myFieldInfo[ i ].IsFamily);
}
}
}
When it prints out the Fieldtype, that reports:
Name : abc
Declaring Type : ConsoleApplication1.Holder
IsPublic : True
MemberType : Field
FieldType : System.Collections.Generic.Dictionary`2[System.String,System.String]
IsFamily : False
Good luck.
SkyMike99
I am trying to write a code that works on some runtime classes which I have no control with. I want to be able to tell the field names, types and values of those classes. With this capability I want to finally compare two instances of the same type and record the differences. For example I want to write a function like this:
void GetObjectDifference(object obj1, object obj2)
where obj1 and obj2 are independent instances of the same complex type.
The output of this function will be an xml file that describes the difference to very detail. So far, I have come to a point that my code works fine with primitive, string, value type, list, hash table and so on. But when a field is of type Dictionary<TKey, TValue>, then I have problem to tell its contained keys and values, since I can not cast the entries to a known type, such as DictionaryEntry or Dictionary<object, object>. I also could not find a powerful system utility function that is similar to FieldInfo.GetVaue, but can do something like EntryInfo.GetKey.
Is this explanation better
ofa
Bruce H
Interesting things! But how do you use boundKvp in the red area of foreach Or how else it could help
foreach (KeyValuePair<int, string> kvp in myDictionary)