Ein Objekt (mit einem privaten MethodInfo
-Feld), das mit Version 1.0 einer Assembly serialisiert ist, wird nicht mit der Version 1.1 dieser Assembly deserialisiert (ein SerializationException
wird geworfen, weil die erforderliche Methode nicht gefunden wurde).
Ich habe festgestellt, dass in .NET 4.5 der Mechanismus der Serialisierung von MemberInfo
via MemberInfoSerializationHolder
geändert wurde. In der Vergangenheit (bis .NET 4.0) waren die serialisierten Daten die Methodensignatur (erhalten mit einem einfachen MethodInfo.ToString()
).
Laut Kommentaren im .NET-Quellcode haben sie eine zweite Signatur hinzugefügt, die über SerializationToString()
weil:
m_signature speichert die ToString () - Repräsentation des Members, die manchmal mehrdeutig ist. Mehrere Überladungen der gleichen Methoden oder Eigenschaften können identisch sein ToString (). m_signature2 speichert die SerializationToString () - Repräsentation, die für jedes Mitglied eindeutig sein sollte. Es ist nur geschrieben und verwendet von Post 4.0 CLR-Versionen.
Für was ich sehen kann, verwendet der MemberInfoSerializationHolder.GetRealObject()
diesen (vereinfachten) Code, um die Methode (vom .NET Quellcode) aufzulösen:
In diesem Fall schlägt die Deserialisierung fehl, weil die m_signature2
-Signatur nicht gefunden werden kann, da der Assemblyname Versionsinformationen enthält und String.Equals()
nicht mit MyAssembly, Version=1.0.0.0
mit MyAssembly, Version=1.1.0.0
übereinstimmt und eine Ausnahme ausgelöst wird.
Ich würde erwarten, dass das Framework auf die alte Suchmethode zurückfällt, wenn die neue Suche fehlschlägt (zumindest wegen der Kompatibilität mit dem vorhandenen Code). Ich verstehe nicht, warum dieser Vergleich mit einem String.Equals()
durchgeführt wird, nachdem die gesamte Version einer Assembly zur Laufzeit aufgelöst wurde (und die neuere Version wird standardmäßig geladen). Ich bin damit einverstanden, dass die Assembly-Version nicht aufgelöst werden kann Dort kann es jedoch entfernt / ignoriert werden, wenn die strikte Suche fehlschlägt.
Ich weiß, dass es schrecklich ist, ein MethodInfo
zu serialisieren, aber in diesem Moment kann diese Korrektur zu viele Änderungen (sowohl in Architektur als auch Code) beinhalten und niemand würde dieses Refactoring in diesem alten Code starten (außerdem muss Binärkompatibilität für Archive sein in beiden Richtungen für alte und neue Versionen behalten).
Bisher habe ich es nicht versucht, aber ist dieses Thema auch für die Delegierten anwendbar? Gibt es eine Lösung (mit Attributen oder mit kleinen Codeänderungen), um dieses Problem zu umgehen?
Endlich konnte ich dieses Problem nicht alleine lösen. Ich habe versucht, ISerializable
mit einer benutzerdefinierten Implementierung von MemberInfoSerializationHolder
zu implementieren, um das alte Verhalten nachzuahmen (einfach Code von Version 4.0 eingefügt). Es funktioniert gut für neue Archive, aber es funktioniert nicht mit alten (bereitgestellten) Anwendungen für dieses Szenario.
Ich habe keine Möglichkeit gefunden, dieses Problem zu lösen, da bereits ausgelieferte Anwendungen nicht funktionieren (es sei denn, ein Patch wird angewendet, aber das war nicht praktikabel).
Ich habe gesehen, dass sich die Implementierung in neueren Builds etwas geändert hat. Das Problem ist nur dann voreingestellt, wenn es mehr als eine Methode mit demselben Namen gibt (Signatur wird dann verwendet), ansonsten wird nur die erste (und einzige) ohne zusätzliche Prüfung ausgewählt.
Der beste Weg, an den ich denken kann, ist die Implementierung von ISerializable
( MSDN )
Durch die Implementierung dieser Schnittstelle für die Objekte mit MethodInfo
Eigenschaften haben Sie nahezu vollständige Kontrolle über die Serialisierung / Deserialisierung.
Der Nachteil ist, dass Sie auch alle anderen Eigenschaften auf eine generische Weise behandeln müssen. Sollte jedoch machbar sein.
Tags und Links .net .net-4.5 serialization