2009-09-26 7 views
7

Ich experimentiere mit WCF RESTful Web-Services und ich habe ein Problem mit Auto-Implementierten Eigenschaften.WCF Xml Serialisierung und AutoImplemented Eigenschaften

Ich habe eine Klasse namens DeviceDescriptor, wie folgt definiert:

public class DeviceDescriptor 
{ 
    public string DeviceId { get; set; } 
    public string DisplayName { get; set; } 
} 

ich einen RESTful WCF-Dienst haben, soll eine Liste der DeviceDescriptors zurückzukehren - hier ist mein Servicevertrag:

[ServiceContract] 
public interface IChooser 
{ 
[WebGet(UriTemplate="/Chooser/RegisteredDevices")] 
[OperationContract] 
List<DeviceDescriptor> RegisteredDevices(); 

[WebGet(UriTemplate = "/Chooser/Ping")] 
[OperationContract] 
string Ping(); 
} 

Nun, es funktioniert irgendwie, außer dass in der XML-Ausgabe die Eigenschaftsnamen nicht richtig ausgegeben werden, es sieht so aus, als ob der Serializer die "unaussprechbaren Namen" der automatisch erzeugten Unterstützungsfelder anstelle der Eigenschaftsnamen verwendet. Meine Ausgabe kommt so aus:

<DeviceDescriptor> 
    <_x003C_DeviceId_x003E_k__BackingField>Pipe.Dome</_x003C_DeviceId_x003E_k__BackingField> 
    <_x003C_DisplayName_x003E_k__BackingField>Pipe diagnostic tool</_x003C_DisplayName_x003E_k__BackingField> 
</DeviceDescriptor> 

Also gibt es einen Ausweg? Warum verwendet WCF nicht die Eigenschaftsnamen?

+0

Das Paradox Stackoverflow: Ich verdienen nur die ‚beliebte Frage‘ Abzeichen für diesen Titel, aber es gibt nur eine upvote. –

Antwort

4

Es verwendet Reflexion, um sie IIRC zu erhalten, wenn Sie mehr Kontrolle möchten, sollten Sie versuchen, einen DataContract zu verwenden, ermöglicht es Ihnen, die genauen Namen anzugeben ([DataMember(Name = "DeviceID")]). Siehe auch die Dokumentation auf DataMemberAttribute

+0

Das hat es getan. Ich musste ein Attribut [DataContract] für die Klasse und dann [DataMember (Name = "xxx")] -Attribute für die Eigenschaften shazamm setzen. Es ist ein bisschen stinkend.Ich frage mich, warum WCF die vermeintlich privaten auto-implementierten Backing-Felder findet und diese anstelle der öffentlichen Property-Namen verwendet? Der C# -Compiler muss eine zweifelhafte Codegenerierung durchführen. –

+0

Wie ich schon sagte, verwendet es wahrscheinlich die Reflektion, um den Speicherort für den Eigenschaftswert zu erhalten, nicht den Namen der Eigenschaft selbst. aber ich bin kein Experte für WCF, also solltest du vielleicht eine Frage stellen, wie WCF die Namen tatsächlich entdeckt;) – Anteru

+0

(du hast die Hauptfrage vollständig beantwortet; aber um den Kommentaren zu folgen, berühre ich kurz die folgenden Punkte) –

9

Um Details zu der Frage hinzuzufügen, die Sie in den Kommentaren fragen ... in den guten alten (3,0) Tagen war WCF/DataContractSerializer ziemlich streng. Wenn Ihr Typ nicht explizit als [DataContract] (oder IXmlSerializable für Fallback) markiert wurde, würde es nicht serialisieren. Es verwendete die als [DataMember] markierten Mitglieder, wobei der explizite Name des Attributs verwendet wurde, falls angegeben, oder der Mitgliedsname anderweitig. Das Leben war gut.

In jüngerer Zeit wurde der Code geändert, so dass "normale" Typen serialisiert werden können - also: ohne Datenverträge. Dies geschieht unter Verwendung des gleichen Ansatzes, wie er BinaryFormatter verwendet - d. H. Er arbeitet bei dem Feld - Level. Dies ist IMO schlecht:

  • Felder sind die Umsetzung, nicht der Vertrag
  • es ist spröde, wenn Sie ändern ... nichts!
  • es braucht nicht viel Wasser gegen Verschleierung halten
  • etwas so unschuldig, wie Schalter zu/von einer Auto-Prop brechen (auto-props wirklich bizarre Feldnamen haben, dass nicht in regelmäßigen C# emuliert werden kann)

ich weiß warum dies war verlockend (WCF erlaubt beliebige Typen zu transportieren), aber jede Sehne in meinem Körper sagt, dass dies ein Nettoverlust ist. Es ist viel besser, Leute dazu zu bringen, die richtigen Werkzeuge (Datenverträge) zu benutzen, als ihre gebrochenen Klassen arbeiten zu lassen. In der ursprünglichen Version 3.0 wäre eine Ausnahme ausgegeben worden, die Ihnen erzählt, wie Sie das richtig beheben können: Markieren Sie es als [DataContract] und teilen Sie ihm mit, welche [DataMember] s Sie serialisieren möchten.

Siehe auch: Obfuscation, serialization and automatically implemented properties

+0

Ich muss Ihnen zustimmen - diese Änderung ist nicht nur schlecht in der Praxis, sondern "fühlt sich auch" falsch an, da sie gegen die Opt-in-Philosophie, die schon so lange existiert, verstößt. –