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?
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
.
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.
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 ...
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.