0

我有这个方法

public string DictionaryToString<T, U>(Dictionary<T, U> dict)
{
  var valueStrings = dict.Select(x => x.Key.ToString() + ": " + x.Value.ToString());
  return String.Join("\n", valueStrings);
}

我有这个我想传递给它的对象

if ((value !=null) && value.GetType().IsGenericType &&
  value.GetType().GetGenericTypeDefinition() == typeof (Dictionary<,>))
{
   var castValue = value as Dictionary<,>; // this cast does not work
   return DictionaryToString(castValue);
}
else
{
  return value.ToString();
}

我可以在.Net 4.5中使用这样的反射代码

var targetMethodInfo = typeof(MyType).GetMethod("DictionaryToString");
var valueTypeArgs = value.GetType().GenericTypeArguments;
var genericMethod = targetMethodInfo.MakeGenericMethod(valueTypeArgs);
var result = genericMethod.Invoke(this, new[] {value });
return result.ToString();

Type.GenericTypeArguments在 .Net 4.5 中是新的。那么我怎样才能在.Net 4.0 中做到这一点呢?

4

5 回答 5

3

您只调用ToString键和值,因此只需让此方法采用IDictionary(非泛型),您没有使用任何类型特定于Tor的东西U

然后,您可以简单地将所有参数转换为IDictionary

var d = arg as IDictionary;

if (d != null)
{
    var res = DictionaryToString(d);
}

您可能还需要修改DictionaryToString实现:

static string DictionaryToString(IDictionary d)
{
    var vals = new List<string>();

    foreach (DictionaryEntry de in d)
    {
        vals.Add(de.Key.ToString() + ": " + de.Value.ToString());
    }

    return String.Join("\n", vals);
}

或者,如果您真的想使用 LINQ,您可以尝试转换为dynamic(无法转换为其他任何内容,因为这可能是通用字典 ( KeyValuePair<>) 或非通用哈希表 ( DictionaryEntry)):

var valueStrings = d.Cast<dynamic>().Select(de => de.Key.ToString() + ": " + de.Value.ToString());
return string.Join("\n", valueStrings);

这基本上是“鸭子类型”的KeyValue属性的存在。

于 2012-12-12T13:36:32.870 回答
1

这听起来可能是旧System.Collections命名空间的情况:

    private static string DictionaryToString(IDictionary dict) {
        if (null == dict) throw new ArgumentNullException("dict");

        var valueStrings = new List<string>();
        foreach (DictionaryEntry item in dict) {
            valueStrings.Add(item.Key + ": " + item.Value);
        }
        return string.Join("\n", valueStrings.ToArray());
    } 

    private static string Test(object value) {

        var dict = value as IDictionary;
        if (dict != null) {
            return DictionaryToString(dict);
        }

        if (value == null) {
            return null;
        }

        return value.ToString();
    }

    private static void Main(string[] args) {

        var aDictionary = new Dictionary<int, string> {
            { 1, "one" },
            { 2, "two" },
            { 3, "three" }
        };

        Console.WriteLine(Test(aDictionary));

        var anotherDictionary = new Dictionary<string, object> {
            { "one", 1 },
            { "two", "2" },
            { "three", new object() }
        };

        Console.WriteLine(Test(anotherDictionary));

        Console.ReadLine();
    }

推理:

非泛型IDictionary将是键值对的集合,其中键是 an object,值是 an objectobjectsupport的所有实例ToString,因此集合的所有键和值都可以转换为 astring而无需知道它们的具体类型。

这不起作用的原因:

var castValue = value as Dictionary<,>

是因为泛型类型Dictionary<TKey, TValue>需要 2 个类型参数。没有这些类型参数,集合就不是通用的。IDictionary如果您在编译时不知道键或值类型,最好使用非泛型。

于 2012-12-12T13:43:24.833 回答
0

GetGenericTypeDefinition 可用于以前的版本http://msdn.microsoft.com/en-us/library/system.type.getgenerictypedefinition(v=vs.100).aspx。我认为 MSDN 上的 4.5 页面缺少“其他版本”下拉菜单。

于 2012-12-12T13:31:20.267 回答
0

为什么不?

if ((value !=null) && value.GetType().IsGenericType &&
       value.GetType().GetGenericTypeDefinition() == typeof (Dictionary<,>))
{
   return DictionaryToString(castValue);
}
else
{
  return value.ToString();
}
于 2012-12-12T13:32:08.910 回答
0

您可以dynamic在 .NET 4.0 中转换为。事先typeof(Dictionary<,>)检查将确保您不会遇到运行时错误。

var castValue = value as dynamic;
return DictionaryToString(castValue);
于 2012-12-12T13:35:44.043 回答