Dlaczego właściwości bez metody ustawiającej nie są serializowane

101

Mam klasę możliwą do serializacji i jedna z właściwości w mojej klasie generuje Guidw getterze. Właściwość nie implementuje metody ustawiającej i jest ignorowana podczas serializacji. Dlaczego tak jest i czy zawsze muszę implementować metodę ustawiającą, aby moja właściwość została serializowana.

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

Próbowałem zaimplementować pusty ustawiacz i został on poprawnie zserializowany.

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

Aktualizacja :

Czy możesz wskazać, jak mam zdefiniować właściwości, których wartości nigdy się nie zmieniają, lub te, dla których wartość jest generowana wewnętrznie?

Konstantin Dinev
źródło
1
Drugi przykład serializacji poprawnie ... Ale co się stanie, gdy spróbujesz go deserializować?
LightStriker
Wypróbuj YAXLib [+ , + ]
Sina Iravanian
3
FYI, serializator XML ignoruje [Serializable].
John Saunders
@JohnSaunders Nie byłem tego świadomy.
Konstantin Dinev

Odpowiedzi:

60

Jest to ograniczenie polegające na XmlSerializertym, że nie serializuje właściwości tylko do odczytu, to, co zrobiłeś w drugim przykładzie, jest zasadniczo hackem, aby go serializować, jednak jest bezużyteczny, jeśli potrzebujesz go później deserializować.

Alternatywnie możesz przełączyć się na używanie DataContractSerializer , jest to bardziej elastyczne.

James
źródło
8
DataContractSerializer wymaga również metod ustawiających. Jest to ograniczenie, ponieważ nawet jeśli możemy go używać tylko do jednego typu operacji, powiedzmy deserializacji, ale deklaracje muszą dotyczyć obu, w przeciwnym razie proces serializacji nie będzie wiedział, co zrobić z wartością, gdy próbuje serializować XML na obiekty.
ryadavilli
7
@ryadavilli wszystko oznaczone jako [DataMember]serializowane przy użyciu DataContractSerializer(tylko do odczytu lub nie).
James
1
@James Napisałem powyższe, ponieważ dostałem błędy podczas kompilacji, gdy próbowałem tego samego. Teraz, kiedy wróciłem do mojego kodu i usunąłem setter, wydaje się, że kompilacja przebiega dobrze. To jest bardzo dziwne i prawdopodobnie praca domowa dla mnie, aby dowiedzieć się więcej na ten temat.
ryadavilli
3
Ahhh w końcu znalazłem źródło mojego zamieszania. Metoda ustawiająca właściwości nie jest wymagana do serializacji. Jeśli jednak właściwość nie ma metody ustawiającej, kod XML nie zostanie deserializowany do obiektu. Tam praca domowa skończona.
ryadavilli
1
@ryadavilli tak, dokładnie, to tylko ograniczenie XmlSerializerimplementacji, opiera się na publicznej metodzie ustawiającej. DataContractSerializerjest nieco sprytniejszy w tym sensie (prawdopodobnie wykorzystując refleksję, aby ustawić pole za kulisami).
James
10

Zobacz „ Wprowadzenie do serializacji XML ” w dokumentacji MSDN. Między innymi mówi:

Elementy, które można serializować

Następujące elementy można serializować przy użyciu klasy XmlSerializer:

Public read/write properties and fields of public classes.

Classes that implement ICollection or IEnumerable.

Uwaga:

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

XmlNode objects.

DataSet objects.

Zobacz też „ Dlaczego klasa XML-Serializable wymaga konstruktora bez parametrów


Ponadto IXmlSerializable

Oprócz powyższych typów, które mogą być serializowane przez serializator XML, można serializować i deserializować każdy typ, który implementuje interfejs IXmlSerializable. W szczególności oznacza to, że typy XElement i XDocument mogą być serializowane.

Zobacz „ Interfejs IXmlSerializable ”.

John Saunders
źródło
6

Ograniczenie XMLSerializer- właściwości bez metody ustawiającej nie mogą być serializowane.

Ale możesz użyć DataContractSerializerdo serializacji private setter properties-

[DataMember]
public string Id
{
    get
    {
         return Guid.NewGuid().ToString();
    }
    private set {}
}
Rohit Vats
źródło
Właściwość ma być serializowana jako atrybut xml (patrz oryginalny post). Twój kod (atrybut DataMember) tworzy element xml. O ile wiem, nie ma (czystego) sposobu, aby powiedzieć DataContractSerializer, aby zamienił właściwość w atrybut, a nie element. DataContractSerializer jest fajny, ale zawsze musisz pamiętać o tym ograniczeniu.
sth_Weird
2

jeśli chcesz mieć prywatne metody ustawiające i mieć obiekt, który można serializować / deserializować, zaimplementuj ISerializable i utwórz konstruktor, taki jak MyObject (informacje o SerializationInfo, kontekst StreamingContext). Przykład znajduje się tutaj .

edamon
źródło
0

Atrybuty serializacji są używane do serializacji i deserializacji obiektów. XmlSerializer przyjmie, że nie trzeba serializować żadnej właściwości, która nie ma metody ustawiającej. Setter będzie używany podczas deserializacji ciągu do obiektu, ponieważ należy utworzyć wystąpienie obiektu, a następnie ustawiający zostanie użyty do wypełnienia wartości właściwości.

Rui Jarimba
źródło