首页 > 解决方案 > 在运行时(可能使用反射)调用泛型方法时,我可以指定“T”吗?

问题描述

我有许多 JSON 文件,每个文件都包含一个不同类对象的列表。

我可以从文件名中计算出我期望的数据,并有一个通用的 JSON 文件阅读器,它返回正确的数据,但我不知道如何将它分配给调用方法中允许我访问结果的任何内容作为实际类型。

我目前正在使用这条线:

var k = ReadJson<dynamic>(filePath, typeof(List<>).MakeGenericType(new[] { type }));

或者

var k = ReadJson<Object>(filePath, typeof(List<>).MakeGenericType(new[] { type }));

但他们都给了我

无法将“System.Collections.Generic.List`1[Abc.Shared.Models.Location]”类型的对象转换为“System.Collections.Generic.List`1[System.Object]”类型。

猜想:既然我不能直接调用ReadJson,我可以通过反射来调用ReadJson,指定泛型'T'的类型吗?如果可能的话,我无法解决。

(为了完整起见,这里是通用方法 - 我认为问题不在这里)

    public static List<T> ReadJson<T>(string filePath, Type t) where T : class, new()
    {
        List<T> regions = new List<T>();

        using (StreamReader file = System.IO.File.OpenText(filePath))
        {
            JsonSerializer serializer = new JsonSerializer();
            regions = (List<T>)serializer.Deserialize(file, t);
        }

        return regions;
    }

标签: c#genericsreflection

解决方案


您不能强制List<T>转换为List<TBase>(并且object是所有引用类型的基础),因为List<T>它不是协变的。你可以投到IEnumerable<T>IEnumerable<TBase>因为IEnumerable<T>协变的。由于历史原因,甚至数组也是协变的,因此您可以T[]转换为TBase[]. 我会给你两个样本:

public static IEnumerable<T> ReadJson1<T>(string filePath, Type t) where T : class, new()
{
    IEnumerable<T> regions = new List<T>();

    using (StreamReader file = System.IO.File.OpenText(filePath))
    {
        JsonSerializer serializer = new JsonSerializer();
        regions = (IEnumerable<T>)serializer.Deserialize(file, t);
    }

    return regions;
}

public static T[] ReadJson2<T>(string filePath, Type t) where T : class, new()
{
    using (StreamReader file = System.IO.File.OpenText(filePath))
    {
        JsonSerializer serializer = new JsonSerializer();
        var regions = (T[])serializer.Deserialize(file, t);
        return regions;
    }
}

Type type = typeof(MyObject);
IEnumerable<object> k1 = ReadJson1<object>("test.json", typeof(List<>).MakeGenericType(new[] { type }));
object[] k2 = ReadJson2<object>("test.json", type.MakeArrayType());

推荐阅读