1

我有一个通过反射调用最终得到的对象:

object readOnlyCollectionObject = propertyInfo.GetValue(someEntity, null);

我知道这个对象是一个通用的 ReadOnlycollection。它可能是ReadOnlyCollection<Cat>,ReadOnlyCollection<Dog>等。为了论证起见,让我们说它是ReadOnlyCollection<T>.

即使 Dog 派生自一个对象,我也知道 aReadOnlyCollection<Dog>不是派生自 a ReadOnlyCollection<object>。所以即使我使用反射调用CopyTo方法我仍然需要知道ReadOnlyCollection的具体类型,这是我想要避免的。

我想知道如何将所有元素作为对象引用数组从 ReadOnlyCollection 中取出,而无需知道ReadOnlyCollection<T>.

4

5 回答 5

4

许多其他答案都提到了 Cast() 和 ToArray,它们的类型都有问题。正如您所说,您不会知道您的属性将实现哪个专门的 IEnumerable。但是,您可以确定它们都将实现非泛型 ICollection 接口。

ICollection readOnlyCollectionObject = (ICollection)propertyInfo.GetValue(someEntity, null);
object[] objs = new ArrayList(readOnlyCollectionObject).ToArray();

或者

ICollection readOnlyCollectionObject = (ICollection)propertyInfo.GetValue(someEntity, null);
object[] objs = new object[readOnlyCollectionObject.Count];
for (int i = 0; i < readOnlyCollectionObject.Count; i++)
    objs[i] = readOnlyCollectionObject[i];

编辑:忘记将演员表从 IEnumerable 更新为 ICollection

于 2009-03-10T11:47:02.640 回答
3

好吧,您可以在只读集合上使用Cast扩展方法,然后将其转换为对象数组,但基于 c# 数组是协变的事实,您可以简单地执行以下操作:

object[] objs = myReadOnlyCollection.ToArray();

(编辑)

正如 Pop Catalin 所提到的,唯一有效T的是引用类型。否则使用 Cast 方法。

(编辑2)

你对问题的更新改变了很多事情......我认为你想要做的事情是不可能的。您想在编译时强制转换为仅在运行时可用的显式类型。在这种情况下,您必须访问集合的唯一方法是使用反射。

于 2009-03-10T09:47:37.950 回答
1
 var myArray = readOnlyCollection.Cast<object>().ToArray(); 
于 2009-03-10T09:48:05.517 回答
0

将您的集合转换为对象列表,然后调用 ToArray():

ReadOnlyCollection<string> s;
object[] o = s.Cast<object>().ToArray();

由于扩展方法,仅适用于 C# 3.5。

于 2009-03-10T09:49:23.203 回答
-1

您想要收藏的深层克隆吗?如果您想深度克隆,请尝试以下代码进行内存深度克隆:

// deep copy in separeate memory space
public object Clone()
{
    MemoryStream ms = new MemoryStream();
    BinaryFormatter bf = new BinaryFormatter();
    bf.Serialize(ms, this);
    ms.Position = 0;
    object obj = bf.Deserialize(ms);
    ms.Close();
    return obj;
}
于 2009-03-10T09:48:20.117 回答