我正在尝试编写一个用于REST-API测试的小型框架。我进行了很多反思,遇到了一个我无法解决的问题。
我使用此行提取用户给我的变量作为路径(字符串)
object o = input.GetType().GetProperty(name).propertyInfo.GetValue(input, null);
该对象可以是普通类型T
或List<T>
。
现在,如果它是一个List并且我知道类型很简单,那么我可以使用
List<string> l = (List<string>)o; // I know its a List<string> because the user told me
将对象解析为给定数组。但是我并不总是知道列表中对象的类型,并且
List<object> l = (List<object>)o; // I dont know the type and I dont care
给我一个错误。
类型为“ System.Collection.GenericList [System.String]”的对象不能 转换为“ System.Collection.GenericList [System.Object]”
我可以做些什么来接收对象列表吗?我不希望用户指定类型,因为它只是我要关心的最后一个变量。喜欢
用户想要测试“ object1.a.b.c”,我只需要知道c的类型,因为那是测试运行的地方。
TIA
答案 0 :(得分:7)
您可以将其转换为IEnumerable<object>
,但不能转换为List<object>
。原因是:香蕉列表不是水果列表,因为您可以将苹果放入水果列表中,但不能放入香蕉列表中。由于这两种类型允许不同的操作,所以它们不兼容。
一个序列没有“放入”操作,因此可以使用香蕉列表作为水果的一个序列。同样,您可以将字符串列表用作对象的序列,但不能用作对象的 list 。
此功能称为通用协方差;有关更多信息,请搜索C#协方差,您会发现很多文章解释其工作原理。
尤其要注意协方差仅适用于引用类型;您不能将整数序列用作对象序列。你知道为什么吗?
或者,如果您手头有一个IEnumerable
,则可以使用mysequence.Cast<object>().ToList()
将 any 序列的副本复制到对象列表中。但这是副本,而不是参考转换。
答案 1 :(得分:1)
由于您的问题开始于处理以JSON形式到达服务器的动态对象,因此在转换为POCO之前,使用JSON处理库本身来测试某些特征非常方便。使用newtonsoft的JSON.Net,
var o = JObject.Parse(json);
JToken property = o["a"]["b"]["c"];
if (property != null)
{
if (property.Type == JTokenType.Array)
{
// Process property as array
}
else if (property.Type == JTokenType.Object)
{
// Process property as object
}
// Magnitude of other types
}
我确实了解在最终处理之前需要转换为.NET类型的需求,但是我强烈建议从JObjects开始,因为该库是为此目的而设计的,并且为C#本身没有提供的许多动态操作提供了许多便利的方法。