2010-09-29 9 views
7

Ich versuche, eine Klasse mit einem schreibgeschützten Id-Feld zu erstellen, jedoch habe ich Probleme, den Wert beizubehalten, wenn das Objekt den WCF-Server passiert.WCF DataMember-Attribut für schreibgeschützte Felder?

Ich kann das [DataMember] Attribut auf der öffentlichen Eigenschaft nicht festlegen, da es keine set Methode gibt, und ich möchte es so behalten, wenn möglich, da ich nicht möchte, dass dieser Wert von externen Mitteln geändert wird. Ich kann das Attribut [DataMember] nicht auf das private Feld setzen, da es in teilweise vertraulichen Umgebungen einen Fehler auslöst.

public class MyClass 
{ 
    private int _id; 

    public int Id 
    { 
     get { return _id; } 
    } 

    private string _otherProperties; 

    [DataMember] 
    public string OtherProperties 
    { 
     get { return _otherProperties; } 
     set { _otherProperties = value; } 
    } 
} 

Gibt es eine Möglichkeit, den Wert des Id-Feldes zu halten, während ohne dass mein Eigentum Öffentlichkeit durch den WCF-Server gehen?

+0

http://msdn.microsoft.com/en-us/library/ms733127.aspx: Es sollte keinen Fehler auslösen, wenn Sie eine private Methode haben. Sie können in der Notiz sehen, dass DataContract die Sichtbarkeit der Methode nicht interessiert. –

Antwort

7

Im Allgemeinen sollten Ihre Datenvertragsklassen sehr einfache Datenübertragungsobjekte sein, ohne dass ihnen eine Logik oder eine tiefere Bedeutung zugeordnet ist. Nur Container, um Daten über die Cloud zu transportieren. Sie sollten öffentliche Klassen mit nur einer Reihe von öffentlichen Lese- und Schreibeigenschaften sein. In Ihren Business-Logik-Klassen sollten Sie diese in einige interne Geschäftsentitäten konvertieren und umgekehrt bei der Übertragung von Daten tun.

Dadurch wird das Datenübertragungsmodell von allen internen Entitätsmodellen getrennt und eine optimale Wartbarkeit gewährleistet, sodass Sie Probleme wie die, mit denen Sie konfrontiert sind, vermeiden können, bei denen OO-Designprobleme mit dem WCF-Betriebsverhalten kollidieren.

Bei sehr kleinen Projekten lohnt sich der Aufwand, ein separates Modell zu behalten, nicht. AutoMapper kann helfen, die erforderliche manuelle Arbeit zu minimieren.

Apropos Ihr spezifisches Szenario, ich bin mir nicht sicher, ob ich die Problemstellung genau verstehe. Sie möchten nicht, dass ein Feld geändert wird? Aber dieses Feld ist nur ein Teil des Datenmodells - Teile des Datenmodells werden nie "modifiziert" - es gibt keine "alten" Daten, nur Daten, die Ihr Kunde erstellt. Ihr Client-Code sendet nur ein Datenobjekt an den Server. Wenn der Server sich nicht um ein Mitglied der Klasse kümmert, sollte es es einfach ignorieren.

Es ist nicht so, dass Instanzen der Datenvertragsobjekte auf dem Server existieren und darauf warten, dass Clients sie manipulieren. Ein schreibgeschütztes Feld könnte in einem solchen Szenario konzeptionell sinnvoll sein, bei WCF ist dies jedoch nicht der Fall. Der Client erstellt nur ein Objekt und sendet es an den Server. Wenn Sie nicht möchten, dass der Server Daten abruft, fügen Sie sie entweder nicht dem Datenmodell hinzu oder lassen Sie den Server den Server ignorieren, wenn dies nicht gewünscht ist (falls dies manchmal nur für bestimmte Benutzer erforderlich ist).

+0

Lass mich sehen, ob ich das gerade habe ...Sie schlagen vor, dass jedes Objekt zwei Teile haben sollte: eine DataTransfer (DataContract) -Klasse zum Senden/Empfangen von Daten zum/vom WCF-Server und die eigentliche Klasse selbst, die die Geschäftslogik, INotifyPropertyChanged, Funktionalität usw. enthält? – Rachel

+0

Ja und nein. Die Datenübertragungsobjekte müssen nicht wirklich Eins-zu-eins mit Geschäftslogikobjekten abgebildet werden. Zum Beispiel könnte ich ein großes und komplexes Employee-Geschäftsobjekt haben, aber über meine verschiedenen WCF-Operationen enthülle ich nur die Daten, die für die jeweilige Operation relevant sind. Z.B. UpdateContactInfo (Guid employeeID, ContactInfo info) würde nur die Kontaktinfo enthalten - obwohl sie immer noch Teil meines Mitarbeitergeschäftsobjekts sein könnte. Bei kleinen Szenarien sind das Datenübertragungsobjekt und das Geschäftsobjekt jedoch fast identisch - nur ohne "unerwünschte" Felder (z. B. Kennwort-Hash). – Sander

1

Nein. Das Datenelement muss getter und setter serialisierbar sein. Es liegt in der Verantwortung des Service, zu überprüfen, dass die ID auf dem Client nicht geändert wurde.

7

Sie können dies tun:

public int Id 
{ 
    get; 
    private set; 
} 

Dies wird die Deserializer glücklich halten, während die Leute nicht wirklich stellen Sie die ID-Wert im Stich gelassen. Sie müssen es im Konstruktor oder im Setter einer anderen Eigenschaft festlegen.

Allerdings stimme ich Sanders darin zu, dass Ihr DTO ein dummer Container sein sollte.