如何使用列表中的类型<type>?</type>

时间:2013-11-22 16:31:49

标签: c# linq list generics

我想通过使用类型并保持简单来使我的代码基于约定,但泛型具有自己的复杂性和它自己的学习曲线。

我在列表中有一堆POCO(普通的旧CLR对象),我想在稍后的代码中进行迭代。

var models = new List<Type>();
models.Add(typeof(Person));
models.Add(typeof(Company));

想循环浏览每个列表项:

models.ForEach(m =>
{
    var label = m.FullName;
    // var data = JsonConvert.DeserializeObject<List<typeof(m)>>(""); // doesn't work
    var data = JsonConvert.DeserializeObject<List<m>>(""); // doesn't work either
    ...
}

问题是反序列化行中的“m”无法正常工作。传递它的最佳方法是什么,即制作'List&lt; m&gt;' '列表&lt; T&gt;'我们可以用吗?

3 个答案:

答案 0 :(得分:7)

要使用泛型,你真的需要知道编译时的类型(T,你不知道 - 你知道运行时 。 (警告:它有可能带有反射,但如果出现过载则不需要使用它,如下所述)

有一个overload of DeserializeObject需要Type而不是使用泛型。所以你的代码将是

models.ForEach(m =>
{
    var label = m.FullName;
    var data = JsonConvert.DeserializeObject("",m);
    ...
}

但是,正如您在评论中指出的那样,您实际上需要一个List<T>而不是一个T。您需要一点点反射,只需创建正确的类型即可转到上面的DeserializeObject调用。

var tList = typeof(List<>);  // Type of open List
models.ForEach(m =>
{
    var label = m.FullName;
    var tConvert = = tList.MakeGenericType(m); 
    var data = JsonConvert.DeserializeObject("",tConvert);
    ...
}

您的问题的答案在上面,但我越看越难以看到您可以<{1>}实际做什么。所有 永远 了解datadata。你不能把它投射到任何东西 - 你不知道它是object的列表还是Person的列表。

也许这是一个过于人为的例子,你已经习惯了现实生活中的问题。如果不是,我预见到你的下一个问题是如何处理Company !!

答案 1 :(得分:1)

如果您在编译时不知道类型,可以使用Reflection执行此操作。请考虑以下代码:

models.ForEach(m =>
{
    var mi = JsonConvert.GetType()
                        .GetMethod("DeserializeObject");
    var m = mi.MakeGenericMethod(new[] { m });

    // you pass [null] for the object because it's a [static] method
    // and you don't have to declare [args] if you can express it simply
       // but keep in mind that it's simply an object[]
    m.Invoke(null, args);
}

答案 2 :(得分:1)

另一个解决方案是使用反射调用泛型方法(如果没有任何重载将类型作为参数)

models.ForEach(m =>
{
    MethodInfo method = typeof(JsonConvert).GetMethod("DeserializeObject");
    MethodInfo generic = method.MakeGenericMethod(m);
    generic.Invoke(null, "");
}