web-dev-qa-db-ger.com

Private Mitgliederdaten serialisieren

Ich versuche, ein Objekt in XML zu serialisieren, das eine Reihe von Eigenschaften hat, von denen einige Readonly sind.

public Guid Id { get; private set; }

Ich habe die Klasse [Serializable] markiert und die ISerializable-Schnittstelle implementiert.

Unten ist der Code, den ich zum Serialisieren meines Objekts verwende.

public void SaveMyObject(MyObject obj)
{
    XmlSerializer serializer = new XmlSerializer(typeof(MyObject));
    TextWriter tw = new StreamWriter(_location);
    serializer.Serialize(tw, obj);
    tw.Close();
}

Leider fällt es in der ersten Zeile mit dieser Nachricht um.

InvalidOperationException wurde nicht behandelt: Eine temporäre Klasse kann nicht generiert werden (Ergebnis = 1) . Fehler CS0200: Eigenschaft oder Indexer 'MyObject.Id' kann nicht zugewiesen werden - es ist nur lesbar

Wenn ich die Id -Eigenschaft auf public setze, funktioniert das einwandfrei. Kann mir jemand sagen, ob ich etwas mache oder zumindest, wenn es überhaupt möglich ist?

73
Jon Mitchell

Sie können DataContractSerializer verwenden (beachten Sie jedoch, dass Sie keine XML-Attribute verwenden können - nur XML-Elemente):

using System;
using System.Runtime.Serialization;
using System.Xml;
[DataContract]
class MyObject {
    public MyObject(Guid id) { this.id = id; }
    [DataMember(Name="Id")]
    private Guid id;
    public Guid Id { get {return id;}}
}
static class Program {
    static void Main() {
        var ser = new DataContractSerializer(typeof(MyObject));
        var obj = new MyObject(Guid.NewGuid());
        using(XmlWriter xw = XmlWriter.Create(Console.Out)) {
            ser.WriteObject(xw, obj);
        }
    }
}

Alternativ können Sie IXmlSerializable implementieren und alles selbst erledigen - dies funktioniert jedoch zumindest mit XmlSerializer.

60
Marc Gravell

Sie könnten den System.Runtime.Serialization.NetDataContractSerializer verwenden. Es ist leistungsfähiger und behebt einige Probleme des klassischen Xml-Serializers.

Beachten Sie, dass es unterschiedliche Attribute für diesen gibt.

[DataContract]
public class X
{
  [DataMember]
  public Guid Id { get; private set; }
}


NetDataContractSerializer serializer = new NetDataContractSerializer();
TextWriter tw = new StreamWriter(_location);
serializer.Serialize(tw, obj);

Bearbeiten:

Update basierend auf Marcs Kommentar: Sie sollten wahrscheinlich System.Runtime.Serialization.DataContractSerializer für Ihren Fall verwenden, um ein sauberes XML zu erhalten. Der Rest des Codes ist derselbe.

6

Schreibgeschützte Felder werden nicht mit der Variable XmlSerializer serialisiert. Dies liegt an der Natur des Schlüsselworts readonly 

Von MSDN:

Das Schlüsselwort readonly ist ein Modifikator, den Sie für Felder verwenden können. Wenn eine Felddeklaration einen Readonly-Modifizierer enthält, können Zuweisungen zu den durch die Deklaration eingegebenen Feldern nur als Teil der Deklaration oder in einem Konstruktor in derselben Klasse erfolgen.

Also ... Sie müssten den Feldwert im Standardkonstruktor festlegen ... 

2
flalar

Mit diesem bestimmten Serialisierungsmodus ist dies nicht möglich (siehe Problembehebung in den anderen Kommentaren). Wenn Sie den Serialisierungsmodus wirklich beibehalten möchten, müssen Sie die Rahmenbedingungen für diesen Modus umgehen. Siehe dieses Beispiel

Markieren Sie grundsätzlich die Eigenschaft public, werfen Sie jedoch eine Ausnahme aus, wenn auf eine andere Zeit als die Deserialisierung zugegriffen wird.

0
jvenema