使用反射将 List<object> 转换为 List<T>

6

我正在编写一个JSON转换器,其中一些属性被装饰为映射指定。我使用反射来使用该映射描述确定要创建的对象类型及其映射方式。以下是一个示例...

[JsonMapping("location", JsonMapping.MappingType.Class)]
    public Model.Location Location { get; set; }

我的映射在处理集合时出现问题...

[JsonMapping("images", JsonMapping.MappingType.Collection)]
    public IList<Image> Images { get; set; }

问题在于我无法将List转换为属性的列表类型。
private static List<object> Map(Type t, JArray json) {

        List<object> result = new List<object>();
        var type = t.GetGenericArguments()[0];

        foreach (var j in json) {
            result.Add(Map(type, (JObject)j));
        }

        return result;
    }

这个方法返回一个列表,但是使用反射时需要先实现 IConvertable 接口再进行 property.SetValue 操作。

有没有更好的方式来处理这个问题?


可能没有什么区别,但你尝试过将Map的返回类型更改为IList<object>(或反之亦然)吗? - Matthew Groves
你需要支持逆变性的 IList<T> 才能这样做。C# 不支持逆变性,所以你不能将 IList<string> list = new List<object>(); 进行赋值。 - Andreas
我可以将类型更改为IList<object>,但我希望它是IList<User>或我指定的任何类型,这样当人们使用库时,事情就会被整齐地映射。 - Burke Holland
你看过Json.NET了吗?这个库也许可以满足你的需求。 - Andreas
它正在使用Json.NET将JSON字符串转换为对象。我只是想再往前走一步,进行一些自定义映射。 - Burke Holland
1个回答

2
您可以使用 Type.MakeGenericType 创建正确类型的 List 对象:
private static IList Map(Type t, JArray json)
{
    var elementType = t.GetGenericArguments()[0];

    // This will produce List<Image> or whatever the original element type is
    var listType = typeof(List<>).MakeGenericType(elementType);
    var result = (IList)Activator.CreateInstance(listType);

    foreach (var j in json)
        result.Add(Map(type, (JObject)j));

    return result;    
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接