1

I have an object that I ended up with via a reflection call:

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

I know this object is a generic ReadOnlycollection. It could be a ReadOnlyCollection<Cat>, ReadOnlyCollection<Dog>, etc. For argument sake, lets just say it is a ReadOnlyCollection<T>.

Even though a Dog derives from an object, I know that a ReadOnlyCollection<Dog> does not derive from a ReadOnlyCollection<object>. So even if I use reflection to call the CopyTo method I still need to know the specific type of ReadOnlyCollection, which is what I want to avoid.

I want to know how to get all the elements out of the ReadOnlyCollection as an array of object references without having to know the specific type (T) of the ReadOnlyCollection<T>.

hkdk3107
  • 13
  • 2
  • 7

5 Answers5

4

Many other answers mention Cast() and ToArray, those all have a problem with the type. As you say, you won't know which specialized IEnumerable your property will implement. However, you can be sure that they will all implement the non-generic ICollection interface.

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

or

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];

Edit: Forgot to update the cast from IEnumerable to ICollection

erikkallen
  • 33,800
  • 13
  • 85
  • 120
3

Well, you can use the Cast extension method on the readonly collection and then convert it to an array of objects but, based on the fact that in c# arrays are covariant, you can simply do:

object[] objs = myReadOnlyCollection.ToArray();

(edit)

As Pop Catalin mentioned, the only works if T is a reference type. Use the Cast method otherwise.

(edit2)

Your update to the question changes things quite a bit ... I think that what you're trying to do is not possible. You want to cast to a explicit Type at compile time that is only available at runtime. In this case, the only way you have to access the collection is with reflection.

bruno conde
  • 47,767
  • 15
  • 98
  • 117
1
 var myArray = readOnlyCollection.Cast<object>().ToArray(); 
user76035
  • 1,526
  • 1
  • 10
  • 12
0

Cast your collection to a list of objects, then call ToArray():

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

Works only in C# 3.5 because of the extension methods.

Gerrie Schenck
  • 22,148
  • 20
  • 68
  • 95
-1

Do you want a deep clone of the collection? If you want to deep clone try this code below for memory deep cloning:

// 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;
}
Patrick Peters
  • 9,456
  • 7
  • 57
  • 106