it-swarm.com.de

Gibt es eine Möglichkeit, ein dynamisches oder anonymes Objekt in ein stark typisiertes, deklariertes Objekt zu konvertieren?

Wenn ich ein dynamisches Objekt oder ein anonymes Objekt habe, dessen Struktur genau der eines stark typisierten Objekts entspricht, gibt es eine .NET-Methode, um ein typisiertes Objekt aus dem dynamischen Objekt zu erstellen?

Ich weiß, dass ich einen LINQ verwenden kann dynamicList.Select(dynamic => new Typed { .... } etwas eingeben, oder ich kann Automapper verwenden, aber ich frage mich, ob es nicht etwas gibt, das speziell dafür gebaut wurde?

36
ProfK

Sie können in ein Zwischenformat serialisieren, um es anschließend zu deserialisieren. Es ist nicht der eleganteste oder effizienteste Weg, aber es könnte Ihre Arbeit erledigen:

Angenommen, dies ist Ihre Klasse:

// Typed definition
class C
{
    public string A;
    public int B;
}

Und dies ist Ihre anonyme Instanz:

// Untyped instance
var anonymous = new {
    A = "Some text",
    B = 666
};

Sie können die anonyme Version in ein Zwischenformat serialisieren und sie dann erneut in eine typisierte Version deserialisieren.

var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
var json = serializer.Serialize(anonymous);
var c = serializer.Deserialize<C>(json);

Beachten Sie, dass dies theoretisch mit jedem Serializer/Deserializer ( XmlSerializer , binärer Serialisierung, anderen json-Bibliotheken) möglich ist, solange der Roundtrip symmetrisch ist.

44

Ihre Frage läuft auf die Frage hinaus: Kann ich eine statisch typisierte Variable in eine andere statisch typisierte Variable (von verschiedenen) konvertieren? Vererbungsketten)? und die Antwort ist offensichtlich Nein.

Warum ist Ihre Frage auf die obige Frage zurückzuführen?

  • Dynamische Typverwendung kompiliert zur Verwendung des Objekttyps mit Reflektion.
  • Ihr Code erhält in Wirklichkeit ein Objekt, das (in Wirklichkeit) einen Wert von einem bestimmten statischen Typ enthält.

Tatsächlich handelt es sich also in Ihrem Code um den statisch eingegebenen Wert, der dem Objekt zugewiesen und zur Kompilierungszeit als dynamisch behandelt wird. Daher ist der einzige Fall, in dem Sie einen statisch typisierten Wert in einen anderen [ohne Reflektion] konvertieren können, der, wenn sie Teil derselben Vererbungskette sind. Andernfalls müssen Sie Reflection explizit (von Ihnen geschrieben) oder implizit (von MS mit dynamischer Verwendung geschrieben) verwenden.

Mit anderen Worten, der folgende Code funktioniert nur, wenn der der Dynamik zugewiesene Wert ein Basis- oder abgeleiteter Typ der Person ist (erfunden für das Beispiel):

dynamic dPerson = GetDynamicPerson();
Person thePerson = (Person)dPerson;

Das wars so ziemlich.

Gut zu erwähnen, Sie können die Werte Byte für Byte mit unsicherem Code kopieren, der auf die Speicheradressen zugreift (wie in C++), aber das ist für mich nichts Besseres als Nachdenken.

13
Tengiz

Hier können wir ein anonymes Objekt in ein Dictionary konvertieren

Dictionary<string, object> dict = 
    obj.GetType()
      .GetProperties()
      .ToDictionary(p => p.Name,  p => p.GetValue(obj, null));

Sie können ein Objekt auch mit LINQ umwandeln:

List<MyType> items = anonymousType.Select(t => new MyType(t.Some, t.Other)).ToList();
6
jherax

Wenn Ihr Objekt von MarshalByRefObject erbt, können Sie RealProxy verwenden.

Eine andere Alternative ist die Verwendung von Reflection. Möglicherweise sind Sie jedoch auf Inhalte beschränkt, die nicht als virtuell gekennzeichnet sind, und/oder müssen Schnittstellen verwenden. Sie können auch die Werte kopieren, sofern die Eigenschaften beschreibbar sind und der leere Konstruktor für Ihren Fall funktioniert.

Die eigentliche Antwort auf Ihre Frage lautet "Nein". Es gibt keine automatische Möglichkeit, ein dynamisches Objekt als einen bestimmten Typ zu behandeln, es sei denn, es handelt sich um eine Instanz dieses Typs. Es gibt auch keine automatische Möglichkeit, die Werte von einem dynamischen/anonymen Objekt in ein zu kopieren Instanz einer benannten Klasse.

Die Laufzeit hat keine Ahnung, was im Konstruktor vor sich geht oder wie die Klasse intern implementiert ist, daher würde jede solche Einrichtung die Sicherheit aus dem Wasser blasen. Der springende Punkt der Dynamik ist es, Enten-Typisierung/Laufzeit-Versand/etc zu ermöglichen.

bearbeiten: Wenn ich die Frage falsch verstanden habe, lassen Sie es mich wissen, aber ich gehe davon aus, dass Sie ein dynamisches Objekt so behandeln möchten, als wäre es eine Instanz von SomeType.

In meinen eigenen Projekten habe ich dafür eine Object Mapper-Klasse verwendet, in der die Eigenschaftsnamen für beschreibbare Eigenschaften und identische oder erzwingbare Typen abgeglichen werden, sodass ich zumindest nicht 10.000 Zeilen Boilerplate schreiben musste, obwohl meine Quelle nicht ' t dynamic, also habe ich Reflection.Emit/DynamicMethod verwendet, um es erheblich zu beschleunigen.

1
russbishop