2009-03-10 7 views
1

Ich habe ein Objekt, das ich mit über eine Reflexion Anruf endete:Objekt [] Von Readonlycollection <T>

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

Ich weiß, dass dieses Objekt eine generische Readonlycollection ist. Es könnte ein ReadOnlyCollection<Cat>, ReadOnlyCollection<Dog>, etc. sein. Für Argument willen, lassen Sie uns einfach sagen, es ist ein ReadOnlyCollection<T>.

Obwohl ein Hund von einem Objekt abgeleitet ist, weiß ich, dass ein ReadOnlyCollection<Dog> nicht von einem ReadOnlyCollection<object> abgeleitet ist. Selbst wenn ich Reflection zum Aufruf der CopyTo-Methode verwende, muss ich den spezifischen Typ von ReadOnlyCollection kennen, was ich vermeiden möchte.

Ich möchte wissen, wie Sie alle Elemente aus der ReadOnlyCollection als ein Array von Objektreferenzen erhalten, ohne den spezifischen Typ (T) von ReadOnlyCollection<T> zu kennen.

Antwort

3

Viele andere Antworten erwähnen Cast() und ToArray, alle haben ein Problem mit dem Typ. Wie Sie sagen, Sie werden nicht wissen, welche spezielle IEnumerable Ihre Eigenschaft implementieren wird. Sie können jedoch sicher sein, dass alle die nicht generische ICollection-Schnittstelle implementieren werden.

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

oder

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: Haben die Besetzung von IEnumerable zu aktualisieren

+0

Problem ist die erste Zeile wird nicht kompilieren, weil Sie nicht von IEnumerable zu ICollection konvertieren können. – hkdk3107

+0

Geändert. Es muss ein schwer zu treffender Tippfehler gewesen sein. – erikkallen

+0

Diese Lösung ist sehr sauber, weil es Generika überhaupt nicht interessiert. – hkdk3107

3

Nun können Sie die Cast Erweiterungsmethode auf der Nur-Lese- Sammlung verwenden und wandeln sie dann in ein Array von Objekten, sondern auf der Grundlage der Tatsache, dass in C# Arrays sind covariant, können Sie einfach tun:

object[] objs = myReadOnlyCollection.ToArray(); 

(edit)

Als Pop Catalin erwähnt, die nur funktioniert, wenn T ein Referenztyp ist. Verwenden Sie andernfalls die Cast-Methode.

(edit2)

Ihr Update auf die Frage ändert sich die Dinge ziemlich viel ... Ich denke, dass das, was Sie versuchen, nicht möglich zu tun ist. Sie möchten einen expliziten Typ bei kompilieren Zeit, die nur verfügbar ist Laufzeit. In diesem Fall müssen Sie nur mit Reflektion auf die Sammlung zugreifen.

+0

Arrays von Referenztypen iCollection covariant sind, wird dies nur funktionieren, wenn T ein Referenztyp ist. –

+0

Bitte haben Sie einen anderen Blick. Ich habe die Beschreibung aktualisiert, um zu zeigen, wie ich dieses Objekt erhalten habe. – hkdk3107

+0

humm. Das ändert die Dinge ziemlich. Siehe mein zweites Update. –

1
var myArray = readOnlyCollection.Cast<object>().ToArray(); 
-1

Wollen Sie einen tiefen Klon der Sammlung? Wenn Sie zu tief Klon wollen diesen Code unten versuchen, für das Gedächtnis tief Klonen:

// 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; 
} 
0

Werfen Sie Ihre Sammlung auf eine Liste von Objekten, dann ruft ToArray():

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

Arbeiten nur in C# 3.5, weil der Erweiterungsmethoden.