c# - 如何将未知类型的 IList(类型在运行时已知)转换为数组?
问题描述
我正在使用反射在运行时复制任何自定义类的对象。我FieldInfo
用来获取所有字段,然后根据它们的类型正确复制它们。
在复制算法开始时我可以使用的唯一类型是System.Object
(AKA object
)。我做了很多类型检查。所以当我的检查方法说这个特定的对象是一些简单的一维数组时,它是数组,毫无疑问。但是,我只能在运行时访问该数组中的元素类型。
我确实成功复制List<type known at runtime>
了这样的:
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;
}
然后我尝试重新编写简单数组的方法:
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, convertedValue) // where convertedValue is object copy from the method above
:
System.ArgumentException: 'Object of type 'System.Object[]' cannot be converted to type 'System.Int32[]'.'
对于该特定示例,数组如下所示:
public int[] Array = { 1, 2, 3 };
最后一件事:我知道如何使用泛型方法解决这个问题MethodInfo ...MakeGenericMethod(...).Invoke
,我只是认为可以避免(也许我错了)。也不能使用序列化。
解决方案
你的线
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<object>
,ToArray()
因此生成一个object[]
。
Array 有一个Clone 方法,可以让你的生活更轻松:
((Array)original).Clone();
如果做不到这一点,您可以使用Array.CreateInstance
.
对于 List 情况,使用 List 的构造函数会更容易,它需要另一个列表来复制:
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;
}
推荐阅读
- json - 为什么 golang 不解码 json 帖子?
- javascript - 如何在 Visual Studio 中配置下划线语法?标签js
- html - 怎么放两个连续?如果我使用内联块,第一个 div 会向下
- git - GitHub 中不再推送分支:为什么?
- javascript - 如何打印字符串的每个字符但在 JavaScript 中有 1 秒的延迟?
- reactjs - react redux 服务器分页和排序
- java - 使用 Java 中的访问密钥和密钥调用 AWS API 网关
- javascript - Adonis 5 build 没有将 env 文件复制到 build 文件夹中
- python - SQLAlchemy 引擎是做什么的?
- ios - 调试:如何观察发布者的数据?