Reputation: 50241
Let's say we have a type that implements IDictionary<string, string>
. It's called MyStringDictionary
.
I'm doing some property/field/method reflection and would like to know if the member is a type that I can convert to an IDictionary<string, object>
.
I know that typeof(IDictionary<string, string>).IsAssignableFrom(typeof(MyStringDictionary))
will be true since both generic parameters match. However, I won't be doing direct assignment to <string, string>
but instead will be converting to <string, object>
, something like this:
public class MyStringDictionary : IDictionary<string, string> {
// Notice that the class itself has no generic type arguments!
}
MyStringDictionary myStringDict = GetBigDictionary();
IDictionary<string, object> genericDict = myStringDict
.ToDictionary(kvp => kvp.Key, kvp => (object) kvp.Value);
How can I determine that this conversion is possible?
I was thinking that I can look to see if it implements IEnumerable<KeyValuePair<,>>
, but again I'm stymied by the fact that I don't know the type argument of the Value
, and don't need to know it because it will just be boxed to object
.
Upvotes: 2
Views: 229
Reputation: 726639
I was thinking that I can look to see if it implements
IEnumerable<KeyValuePair<,>>
Absolutely, that's the way to go! Now for the details of how this can be done: go through results of myObj.GetType().GetInterfaces()
, and call the method below. If you get true
back, second and third parameters would be set to the type of key and the type of value.
private static bool IsEnumKvp(Type t, out Type k, out Type v) {
k = v = null;
if (!t.IsGenericType) return false;
var genDef = t.GetGenericTypeDefinition();
if (genDef != typeof(IEnumerable<>)) return false;
var itemType = t.GenericTypeArguments[0];
if (!itemType.isGenericType) return false;
var genItemDef = itemType.GetGenericTypeDefinition();
if (genItemDef != typeof(KeyValuePair<,>)) return false;
var kvpTypeArgs = genItemDef.GenericTypeArguments;
k = kvpTypeArgs[0];
v = kvpTypeArgs[1];
return true;
}
Calling this method on MyStringDictionary
should produce a true
:
foreach (var t : MyStringDictionary.GetType().GetInterfaces()) {
Type keyType, valType;
if (IsEnumKvp(t, out keyType, out valType)) {
Console.WriteLine(
"Your class implements IEnumerable<KeyValuePair<{0},{1}>>"
, keyType.FullName
, valType.FullName
);
}
}
Note that potentially this method could return true
multiple types.
Upvotes: 2