如何将未知类型(类型在运行时已知)的 IList 转换为数组? [英] How to convert IList of unknown type (type is known at runtime) to array?

查看:32
本文介绍了如何将未知类型(类型在运行时已知)的 IList 转换为数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用反射在运行时复制任何自定义类的对象.我正在使用 FieldInfo 获取所有字段,然后根据它们的类型正确复制它们.

I am using reflection to copy an object of any custom class at runtime. I am using FieldInfo to get all the fields and then properly copy them based on their type.

在复制算法开始时我可以使用的唯一类型是 System.Object(又名 object).我做了很多类型检查.所以当我的检查方法说这个特定对象是一些简单的一维数组时,毫无疑问,它是数组.但是,我只能在运行时访问该数组中元素的类型.

Only type I can work with at the start of the copy algorithm is System.Object (AKA object). I do a lot of type checking. So when my check method says this particular object is some simple one-dimensional array, it is array, no doubt. However I can access the type of elements in that array only at runtime.

我确实成功复制了List,如下所示:

I did successfully copied List<type known at runtime> like this:

public object Get_ListCopy(object original)
{
    Type elementType = original.GetType().GetGenericArguments()[0];
    Type listType = typeof(List<>).MakeGenericType(elementType);

    object copy = Activator.CreateInstance(listType);
    var copyIList = copy as IList;

    foreach (var item in original as IEnumerable)
        copyIList.Add(item);

    copy = copyIList;

    return copy;
}

然后我尝试重新编写简单数组的方法:

Then I tried to re-write the method for simple array:

public object Get_ArrayCopy(object original)
{
    Type elementType = original.GetType().GetElementType();    // difference here
    Type listType = typeof(List<>).MakeGenericType(elementType);

    object copy = Activator.CreateInstance(listType);
    var copyIList = copy as IList;

    foreach (var item in original as IEnumerable)
        copyIList.Add(item);

    copy = Enumerable.Range(0, copyIList.Count).Select(i => copyIList[i]).ToArray();    // difference here

    return copy;
}

但是当使用 FieldInfo.SetValue(copyObject, ConvertValue) 为字段赋值时返回一个异常//其中convertedValue 是从上面的方法复制的对象:

System.ArgumentException: 'Object of type 'System.Object[]' cannot be converted to type 'System.Int32[]'.'

对于那个特定的例子,数组看起来像这样:

For that particular example the array looked like this:

public int[] Array = { 1, 2, 3 };

最后一件事:我知道如何使用泛型方法和 MethodInfo ...MakeGenericMethod(...).Invoke 解决这个问题,我只是认为它可以避免(也许我错了).也不能使用序列化.

One last thing: I know how to solve this problem using generic methods and MethodInfo ...MakeGenericMethod(...).Invoke , I just thought it could be avoided(maybe I am wrong). Also serialization can't be used.

推荐答案

您的线路

copy = Enumerable.Range(0, copyIList.Count)
    .Select(i => copyIList[i])
    .ToArray();

实际上是:

copy = Enumerable.Range(0, copyIList.Count)
    .Select<int, object>(i => copyIList[i])
    .ToArray<object>();

编译器知道copyIList 是一个IList.当您执行 copyIList[i] 时,您可以访问 IList 的索引器,它返回 object.所以 Select 返回一个 IEnumerable,而 ToArray() 因此生成一个 object[].

The compiler knows that copyIList is an IList. When you do copyIList[i], you access IList's indexer, which returns object. So the Select returns an IEnumerable<object>, and the ToArray() therefore generates an object[].

Array 有一个 克隆方法 这将使您的生活更轻松:

Array has a Clone method which will make your life easier:

((Array)original).Clone();

如果失败,您可以使用 Array.CreateInstance.

Failing that, you can instantiate a new array with Array.CreateInstance.

对于 List 的情况,使用 List 的构造函数会更容易,它需要另一个列表来复制:

For the List case, it would be easier to use List's constructor which takes another list to copy:

public object Get_ListCopy(object original)
{
    Type elementType = original.GetType().GetGenericArguments()[0];
    Type listType = typeof(List<>).MakeGenericType(elementType);

    object copy = Activator.CreateInstance(listType, new[] { original });
    return copy;
}

这篇关于如何将未知类型(类型在运行时已知)的 IList 转换为数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆