Erstellen eines SerializationBinder für den Binary Formatter, der das Verschieben von Typen von einer Assembly und von einem Namespace in einen anderen verarbeitet

8

Der Kontext ist wie folgt

  1. Ich möchte Code umgestalten, indem ich ihn in andere Projekte verschiebe
  2. Ein Teil dieses Codes besteht aus serialisierbaren DTOs, die verwendet werden Senden und Empfangen von Daten über mehrere Endpunkte hinweg
  3. Wenn ich den Code verschiebe, bricht die Serialisierung (daher nicht) rückwärts kompatibel mit älteren Versionen meiner Anwendung)

Eine Lösung für dieses Problem ist der SerializationBinder, mit dem ich in gewisser Weise von einem Typ zum anderen "umleiten" kann.

Ich möchte daher einen SerializationBinder erstellen, um diese Anforderung zu erfüllen. Dies muss jedoch durch Erfüllung der folgenden Anforderungen erfolgen.

  1. Die Eingaben für den SerializationBinder sollten eine Liste des alten Typs sein zu neuen Typzuordnungen. Das Mapping sollte die alte Assembly enthalten Name (keine Version, kein öffentlicher Schlüsseltoken) und der alte vollständige Name des Geben Sie (Namespace und Name) sowie den neuen Assemblynamen und neu ein vollständiger Name des Typs
  2. Für die Typen, die in den Eingaben enthalten sind, sollten Versionsnummern von Assemblys ignoriert werden
  3. Es sollte mit Generics umgehen, wenn meine Typen in Generika vorkommen (Liste, Wörterbuch usw.), ohne dass die Generika in die Eingaben
  4. aufgenommen werden müssen
  5. Für alles, was nicht in den Eingaben (d. h. Typen, die nicht haben bewegte oder .NET-Typen wie zum Beispiel Dataset) sollte es standardmäßig sein Verwenden des Out-of-the-Box-Algorithmus des binären Serialisierers

Ist das möglich oder träume ich? Gibt es etwas da draußen, das das schon tut? Ich nehme an, das ist ein häufiges Problem.

Bis jetzt sehe ich keinen einfachen Weg, 3 zu machen und überhaupt nicht 4.

Hier ist ein Versuch

%Vor%     
Mark 29.10.2013, 18:37
quelle

3 Antworten

5

Dies könnte funktionieren (anstelle Ihrer Überschreibung).

%Vor%

Dann müssen Sie nur die Funktion GetFlatTypeMapping implementieren (ohne sich über generische Argumente Gedanken zu machen).

Sie müssen typeof(List<>) und typeof(Dictionary<,>) (oder jedes andere generische Element, das Sie verwenden möchten) zurückgeben, wenn Sie dazu aufgefordert werden.

nb: Ich sagte typeof(List<>) ! nicht typeof(List<something>) ... das ist wichtig.

Haftungsausschluss: wegen der Regex "(? [^]] *)", unterstützt dieser Snipped nicht verschachtelte generische Typen wie List<List<string>> ... Sie werden es ein wenig optimieren müssen um es zu unterstützen!

    
Olivier 12.11.2013 11:06
quelle
0

Obwohl es Ihre Frage möglicherweise nicht beantwortet, könnte dies Ihr Problem lösen:

Ich konnte alle außer einer für die Deserialisierung erforderlichen Assemblierung neben einer Objektstruktur serialisieren. Der Trick besteht darin, die Objektstruktur mithilfe der Reflektion auf Typen und die Assemblys zu überprüfen, in denen sie definiert sind. Sie können dann die Assemblys als binäre Daten in ein Serialisierungsobjekt schreiben und in eine Anwendungsdomäne laden, in der Sie den Rest deserialisieren können der Objektstruktur.

Sie müssen die AppDomain-Behandlung, das Stammobjekt und einige Basisklassen in eine Assembly einfügen, die sich nicht ändert, und alles andere wird in Assemblys in Abhängigkeit von diesem "Anker" definiert.

Upsides:

  • Serialisierung bricht nicht, solange sich die Ankerbaugruppe nicht ändert
  • kann zur Verschleierung verwendet werden, z. Einige erforderliche Assembly kann in jeder Datei
  • versteckt werden
  • kann für Online-Aktualisierungen verwendet werden, z. Versenden Sie die Baugruppe mit beliebigen Daten
  • Soweit es mich betrifft, kein Problem mit Generika

Nachteile:

  • Sicherheitsprobleme, da Bootstrapping verwendet werden könnte, um Code zu injizieren (etwas zusätzliche Arbeit für Assembly SecurityEvidences)
  • AppDomain-Grenzen sind eine Arbeit, die es zu durchqueren gilt
  • sprengt Ihre serialisierten Daten (ok, für Dateien - schlecht, für die Kommunikation)

Aber hey, Kommunikation bricht nicht ab, es sei denn, Sie haben andere Client-Versionen und dann können Sie das Bootstrapping auf Handshake durchführen.

Leider kann ich den Code nicht bereitstellen, da er zu komplex und zu spezifisch ist. Aber ich teile einige Einsichten in diese anderen Antworten von mir:

Unterschied zwischen DataContract-Attribut und Serializable-Attribut in .net

Sie müssen das AssemblyResolve-Ereignis verknüpfen, wenn DisallowApplicationBaseProbing = true ist

    
No answer 07.11.2013 17:03
quelle
-2

Ist es eine schwierige Anforderung, dass Sie den BinaryFormatter für Ihre De / Serialisierung verwenden müssen?

Wenn es nicht schwierig ist, den BinaryFormatter für die Serialisierung zu verwenden, sollten Sie alternative Serialisierungsmethoden wie JSON.Net oder ProtoBuf.Net in Betracht ziehen. Jede dieser Optionen erstellt plattform- und versionsunabhängige Serialisierungen Ihrer Daten.

Alternativ können Sie die binäre Serialisierung selbst durchführen (die sowohl schneller als auch kleiner als der BinaryFormatter ist, aber im Allgemeinen Code-intensiver, da Sie Serializer und Deserializer im Wesentlichen identisch zueinander schreiben müssen.

Wenn Sie BinaryFormatter verwenden müssen, stellen Sie sicher, dass Sie es mit FormatterAssemblyStyle.Simple konstruieren, um Versionierungsprobleme zu umgehen. Das sagt ihm, die pedantische Überprüfung der Assembly-Version nicht zu machen.

    
dodexahedron 05.11.2013 18:52
quelle