如何将通用字典转换为已知类型?

时间:2012-08-23 15:41:15

标签: c# reflection casting

使用反射,我试图掌握一个类字段并填充它们。目前,我检测到Dictionary<,>的实例并创建Dictionary<object,object>来填充。之后它尝试更改类型,但这不起作用并且无法转换:

// Looping through properties. Info is this isntance.
// Check is a dictionary field.
Dictionary<object, object> newDictionary = new Dictionary<object, object>();

// Populating the dictionary here from file.
Type[] args = info.PropertyType.GetGenericArguments();
info.GetSetMethod().Invoke(data, new object[]
    {
        newDictionary.ToDictionary(k => Convert.ChangeType(k.Key, args[0]),
                                   k => Convert.ChangeType(k.Value, args[1]))
    });

有什么想法吗?感谢。

3 个答案:

答案 0 :(得分:9)

您应该手动创建您找到的类型的词典。

Type dictionary = typeof(Dictionary<,>);
Type[] typeArgs = info.PropertyType.GetGenericArguments();

// Construct the type Dictionary<T1, T2>.
Type constructed = dictionary.MakeGenericType(typeArgs);
IDictionary newDictionary = (IDictionary)Activator.CreateInstance(constructed);

// Populating the dictionary here from file. insert only typed values below
newDictionary.Add(new object(), new object());


info.SetValue(data, newDictionary, null);

对于downvotes的证明。

    static void Main(string[] args)
    {
        IDictionary<int, string> test = new Dictionary<int, string>();
        var castedDictionary = (IDictionary)test;
        castedDictionary.Add(1, "hello");
        Console.Write(test.FirstOrDefault().Key);
        Console.Write(test.FirstOrDefault().Value);
        Console.ReadLine();
    }

Dictionary<TKey, TValue>实施IDictionary,在我的示例中我创建了Dictionary<TKey, TValue>Type dictionary = typeof(Dictionary<,>);)的实例。

public class Dictionary<TKey, TValue> : IDictionary<TKey, TValue>, 
    ICollection<KeyValuePair<TKey, TValue>>, IDictionary, ICollection, 
    IReadOnlyDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, 
    IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, ISerializable, 
    IDeserializationCallback

答案 1 :(得分:0)

可能已经晚了,但我遇到了这个问题。 user854301 是绝对正确的。 我需要它在运行时传递一个通用字典,我已经弄清楚了大部分,只是缺少 IDictionary。第一次没用,因为我犯了和 Fyodor Soikin 一样的错误;寻找IDictionary<T,U>。 然而,魔法在System.Collections.IDictionary而不是System.Collections.Generic.IDictionary<>

Type[] types = prop.PropertyType.GetGenericArguments();
Type dictType = typeof(Dictionary<,>).MakeGenericType(types);
IDictionary dict = (IDictionary)Activator.CreateInstance(dictType);
types.Dump();
dictType.GetGenericArguments().Dump();
dict.GetType().GetGenericArguments().Dump();
array.Split(';').ForEach(a =>
{
    dict.Add(MyFunctions.ChangeType(a.Split(',')[0], types[0]), MyFunctions.ChangeType(a.Split(',')[1], types[1]));
}); // List Items
dict.GetType().GetGenericArguments().Dump();
prop.SetValue(newT, dict);

答案 2 :(得分:-1)

创建一个帮助程序泛型类,它可以执行您需要执行的操作并生成正确类型的结果。然后根据运行时已知的类型动态地实例化该类。

interface IHelper
{
    object CreateDictionary ();
}

class Helper<TKey, TValue> : IHelper
{
    public object CreateDictionary ()
    {
        return (whatever).ToDictionary<TKey, TValue>( blah );
    } 
}

var h = Activator.CreateInstance( typeof( Helper<,> ).MakeGenericType( yourKnownKeyType, yourKnownValueType ) ) as IHelper;
info.SetValue( h.CreateDictionary() );

如果经常发生这种情况,您还应该缓存帮助程序实例,以避免每次动态实例化的影响。