Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cast object to a Dictionary<TKey, TValue>

I have a function in C# that operates on generic Dictionary's:

public static string DoStuff<TKey, TValue>(Dictionary<TKey, TValue> dictionary)
{
    // ... stuff happens here
}

I also have a function that loops over objects. If one of those objects is a Dictionary<>, I need to pass it to that generic function. However, I won't know what the types for the Key or Values are at compile-time:

foreach (object o in Values)
{
    if (/*o is Dictionary<??,??>*/)
    {
        var dictionary = /* cast o to some sort of Dictionary<> */;
        DoStuff(dictionary);
    }
}

How do I do this?

like image 237
Ryan Avatar asked Nov 30 '12 22:11

Ryan


2 Answers

Assuming you can't make your method generic in the type of the Values collection, you can use dynamic:

foreach (object o in values)
{
    Type t = o.GetType();
    if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Dictionary<,>))
    {
        string str = DoStuff((dynamic)o);
        Console.WriteLine(str);
    }
}

Alternatively you can use reflection:

foreach (object o in values)
{
    Type t = o.GetType();
    if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Dictionary<,>))
    {
        var typeParams = t.GetGenericArguments();
        var method = typeof(ContainingType).GetMethod("DoStuff").MakeGenericMethod(typeParams);
        string str = (string)method.Invoke(null, new[] { o });
    }
}
like image 192
Lee Avatar answered Oct 02 '22 04:10

Lee


Make your function generic too if you know that all dictionaries in Value collection are the same:

void DealWithIt<T,V>(IEnumerable Values)
{
foreach (object item in Values)
{
    var dictionary = item as Dictionary<T,V>;
    if (dictionary != null)
    {
        DoStuff<T,V>(dictionary);
    }
}

Otherwise consider using non-generic IDictionary to be passed to DoStuff before diving into serious reflection code.

like image 36
Alexei Levenkov Avatar answered Oct 02 '22 05:10

Alexei Levenkov