Warum werden Eigenschaften ohne Setter nicht serialisiert?

100

Ich habe eine serialisierbare Klasse und eine der Eigenschaften in meiner Klasse generiert eine Guidim Getter. Die Eigenschaft implementiert keinen Setter und wird während der Serialisierung ignoriert. Warum ist das so und muss ich immer einen Setter implementieren, damit mein Eigentum serialisiert wird.

[Serializable]
public class Example
{
    [XmlAttribute("id")]
    public string Id
    {
        get
        {
             return Guid.NewGuid().ToString();
        }
    }
}

Ich habe versucht, einen leeren Setter zu implementieren, der korrekt serialisiert wurde.

[Serializable]
public class Example
{
    [XmlAttribute("id")]
    public string Id
    {
        get
        {
             return Guid.NewGuid().ToString();
        }
        set {}
    }
}

Update :

Können Sie darauf hinweisen, wie ich Eigenschaften definieren soll, deren Werte sich nie ändern oder für die der Wert intern generiert wird?

Konstantin Dinev
quelle
1
Das zweite Beispiel ist korrekt serialisiert ... Aber was passiert, wenn Sie versuchen, es zu deserialisieren?
LightStriker
Versuchen Sie YAXLib [+ , + ]
Sina Iravanian
3
Zu Ihrer Information, der XML Serializer ignoriert [Serializable].
John Saunders
@ JohnSaunders Das war mir nicht bewusst.
Konstantin Dinev

Antworten:

59

Es ist eine Einschränkung, dass XmlSerializeres keine schreibgeschützten Eigenschaften serialisiert. Was Sie in Ihrem zweiten Beispiel getan haben, ist im Wesentlichen der Hack, um es zur Serialisierung zu bringen. Es ist jedoch nutzlos, wenn Sie es später zum Deserialisieren benötigen.

Alternativ können Sie zur Verwendung von DataContractSerializer wechseln , es ist flexibler.

James
quelle
8
DataContractSerializer erfordert auch Setter. Dies ist eine Einschränkung, da der Serialisierungsprozess nicht weiß, was mit einem Wert zu tun ist, wenn er versucht, einen zu serialisieren, obwohl wir ihn möglicherweise nur für eine Art von Operation verwenden, z. B. Deserialisierung. Die Deklarationen müssen jedoch für beide gelten XML in Objekte.
Ryadavilli
7
@ryadavilli alles, was als [DataMember]serialisiert markiert ist DataContractSerializer(schreibgeschützt oder nicht).
James
1
@ James Ich habe das oben geschrieben, weil ich einige Fehler bei der Kompilierung bekam, als ich das gleiche versuchte. Als ich nun zu meinem Code zurückkehrte und den Setter entfernte, scheint er gut zu kompilieren. Dies ist sehr seltsam und wahrscheinlich eine Hausaufgabe für mich, mehr darüber zu recherchieren.
Ryadavilli
3
Ahhh fand endlich die Quelle meiner Verwirrung. Ein Eigenschaftssetzer ist für die Serialisierung nicht erforderlich. Wenn eine Eigenschaft jedoch keinen Setter hat, wird das XML nicht zu einem Objekt deserialisiert. Dort waren die Hausaufgaben erledigt.
Ryadavilli
1
@ryadavilli yep genau, es ist nur eine Einschränkung der XmlSerializerImplementierung, es basiert auf der Public-Setter-Methode. DataContractSerializerist in diesem Sinne etwas schlauer (wahrscheinlich mit Reflexion, um das Feld hinter die Kulissen zu setzen).
James
10

Siehe " Einführung in die XML-Serialisierung " in der MSDN-Dokumentation. Unter anderem heißt es:

Elemente, die serialisiert werden können

Die folgenden Elemente können mit der XmlSerializer-Klasse serialisiert werden:

Public read/write properties and fields of public classes.

Classes that implement ICollection or IEnumerable.

Hinweis:

Only collections are serialized, not public properties.
XmlElement objects.

XmlNode objects.

DataSet objects.

Siehe auch " Warum XML-Serializable-Klassen einen parameterlosen Konstruktor benötigen "


Auch IXmlSerializable

Zusätzlich zu den oben genannten Typen, die vom XML Serializer serialisiert werden können, kann jeder Typ, der die IXmlSerializable-Schnittstelle implementiert, serialisiert und deserialisiert werden. Dies bedeutet insbesondere, dass die Typen XElement und XDocument serialisiert werden können.

Siehe " IXmlSerializable Interface ".

John Saunders
quelle
6

Einschränkung von XMLSerializer- Eigenschaften ohne Setter können nicht serialisiert werden.

Aber Sie können verwenden, um DataContractSerializerzu serialisieren private setter properties-

[DataMember]
public string Id
{
    get
    {
         return Guid.NewGuid().ToString();
    }
    private set {}
}
Rohit Vats
quelle
Die Eigenschaft soll als XML-Attribut serialisiert werden (siehe Originalbeitrag). Ihr Code (DataMember-Attribut) erzeugt ein XML-Element. Soweit ich weiß, gibt es keine (saubere) Möglichkeit, den DataContractSerializer anzuweisen, eine Eigenschaft in ein Attribut und nicht in ein Element umzuwandeln. DataContractSerializer ist nett, aber Sie müssen diese Einschränkung immer berücksichtigen.
sth_Weird
2

Wenn Sie private Setter haben möchten und das Objekt serialisierbar / deserialisierbar sein soll, implementieren Sie ISerializable und erstellen Sie einen Konstruktor wie MyObject (SerializationInfo info, StreamingContext context). Ein Beispiel finden Sie hier .

Edamon
quelle
0

Serialisierungsattribute werden zum Serialisieren und Deserialisieren von Objekten verwendet. XmlSerializer geht davon aus, dass Sie keine Eigenschaft serialisieren müssen, die keinen Setter hat. Der Setter wird verwendet, wenn eine Zeichenfolge in ein Objekt deserialisiert wird, da eine Instanz des Objekts erstellt werden muss und der Setter dann zum Auffüllen des Eigenschaftswerts verwendet wird.

Rui Jarimba
quelle