我可以在运行时调用泛型方法时指定'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]"到type"System.Collections.Generic.List`1[System.Object]'.

猜想:由于我不能直接调用ReadJson,我可以通过指定泛型"t"的类型的反射来调用ReadJon吗?我不知道这是否可能。

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

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;
}

不能将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());

尝试以下操作:

public static List<T> ReadJson<T>(string filePath)
{
using (var reader = File.OpenText(filePath))
{
var serializer = new JsonSerializer();
return (List<T>) serializer.Deserialize(reader, typeof(List<T>));
}
}
public static IList ReadJson(string filePath, Type itemType)
{
using (var reader = File.OpenText(filePath))
{
var serializer = new JsonSerializer();
var type = typeof(List<>).MakeGenericType(itemType);
return (IList)serializer.Deserialize(reader, type);
}
}

如果您在设计时知道项目类型,则可以使用第一个版本。如果您在设计时不知道项类型,但在运行时知道,则可以使用第二个版本。在任何情况下,这两个方法都返回一个itemType/T项的列表。

第二个版本被声明为返回IList。这就是我们所能做的,因为我们在设计时不知道项目类型。然而,它返回一个真正的List<T>

你的ReadJson方法是多余的,如果你知道T,那么你就知道t,因为t = typeof(T)。或者你指的是t = typeof(List<T>)

最新更新