我有许多 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;
}
您无法将
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>)