Deserialisieren Sie abgeleitete Typen im WCF-Service als Basistypen, behalten Sie jedoch Typinformationen bei

9

Ich möchte, dass mein Service von BaseType abgeleitete Typen akzeptieren und zurückgeben kann, ohne zu wissen, was diese Typen sind. Ich habe fast eine Lösung mit einem benutzerdefinierten DataContractResolver basierend auf dem SharedTypeResolver aus diesem exzellenten Blogpost .

Das fehlende Teil des Puzzles ist, dass die Typen, mit denen mein Dienst arbeitet, nicht geteilt und dem Dienst bekannt sind, aber ich möchte sie trotzdem akzeptieren und wissen, was der Typ hätte sein sollen. Ich habe das folgende Beispiel für einen Dienst gefunden, der als Stapel fungiert. Sie können jeden Typ, der von BaseType abgeleitet ist, pushen und aufrufen, vorausgesetzt, Sie verwenden SharedTypeResolver und die Typen werden zwischen Client und Server geteilt.

%Vor%

Dies ist offensichtlich ein stark vereinfachtes Beispiel für das Problem, das ich habe. Ein Client kann ziemlich froh sein, BaseType oder DerivedType zu pushen und zu poppen, weil sowohl der Client als auch der Server davon wissen, aber wenn der Client UnsharedType schiebt, was der Dienst nicht weiß, erhalte ich einen Fehler wie erwartet.

  

Der Formatierer hat eine Ausnahme ausgelöst, als er versucht hat, die   Nachricht: Beim Versuch, Parameter zu deserialisieren, ist ein Fehler aufgetreten    Ссылка . Die InnerException Nachricht war 'Fehler in   Linie 1 Position 316. Element ' Ссылка enthält Daten   von einem Typ, der dem Namen "TestWcfClient, Version = 1.0.0.0" zugeordnet ist,   Culture = neutral, PublicKeyToken = null: TestWcfClient.UnsharedType '. Das   Deserializer hat keine Kenntnis eines Typs, der diesem Namen zugeordnet ist.   Erwägen Sie, die Implementierung der ResolveName-Methode in Ihrem System zu ändern   DataContractResolver, um einen Nicht-Null-Wert für name zurückzugeben   'TestWcfClient.UnsharedType' und Namespace 'TestWcfClient,   Version = 1.0.0.0, Kultur = neutral, PublicKeyToken = null '.'. Bitte sehen   InnerException für weitere Details.

Ich denke derzeit daran, IExtensibleDataObject zu BaseType hinzuzufügen, um die Werte eines nicht gemeinsam genutzten Typs zu speichern, und einen nicht gemeinsam genutzten Typ so aussehen zu lassen, als ob ein Element verschoben wird. das Gegenteil müsste passieren, wenn ein Gegenstand geknallt wird. Ich bin mir nicht sicher, wie ich das anstellen soll. Meine bisherigen Gedanken zu möglichen Ansätzen:

  • Weitere Anpassung an BaseType , die ein DataContractResolver beinhalten könnte
  • Verwenden von TypeDelegator anstelle eines nicht freigegebenen Typs
  • Behalten Sie irgendwie die serialisierte XML-Datei bei, die der Dienst erhalten hat, wenn ein Element gepusht wird, und verwenden Sie diese in der Antwort, wenn ein Element aufgerufen wird
  • Verwenden eines Nachrichteninspektors zum Bearbeiten der Nachrichten

Ich habe keine Ahnung, ob etwas davon funktioniert, was beteiligt ist oder was die beste Lösung ist. Hast du?

    
batwad 09.04.2013, 12:51
quelle

1 Antwort

3

Ich habe mit einem Nachrichteninspektor und einem Platzhaltertyp, der IExtensibleDataObject implementiert, einige Fortschritte gemacht. Der Inspector erstellt die eingehende Nachricht und ändert den Typhinweis in den des Platzhalters und fügt den Originaltyp als Eigenschaft hinzu. Wenn der Typ dann in einer Antwort gesendet wird, geschieht das Gegenteil, wodurch der Platzhalter wie der ursprüngliche Typ aussieht.

Meine Beschwerde bei dieser Lösung ist, dass sie an den Dienst gebunden ist, weil ich den XML-Namespace des Dienstes einschließen musste und die Methoden und Parameter, die man verwenden sollte, explizit benennen sollte. Ansonsten scheint es ziemlich gut zu funktionieren, obwohl ich es nur an ziemlich einfachen Typen getestet habe, die von BaseType abgeleitet wurden.

Kann jemand das verbessern? Es gibt eine Prämie für dich.

%Vor%     
batwad 16.04.2013 08:33
quelle