2009-02-26 14 views
10

Próbuję znaleźć sposób na zmianę zachowania serializacji właściwości.Przesłanianie właściwości za pomocą atrybutu

Powiedzmy mam takiej sytuacji:

[Serializable] 
public class Record 
{ 
    public DateTime LastUpdated {get; set; } 

    // other useful properties ... 
} 

public class EmployeeRecord : Record 
{ 
    public string EmployeeName {get; set; } 

    // other useful properties ... 
} 

Teraz chcę serializacji EmployeeRecord. Nie chcę, aby właściwość LastUpdated z klasy Record była serializowana. (Chcę, aby LastUpdated był serializowany, gdy serializuję Record)).

Najpierw próbowałem ukrywanie właściwość LastUpdated za pomocą słowa kluczowego nowy a następnie dodając atrybut XmlIgnore:

public class EmployeeRecord : Record 
{ 
    public string EmployeeName {get; set; } 

    [XmlIgnore] 
    public new DateTime LastUpdated {get; set; } 
    // other useful properties ... 
} 

Ale to nie działa. Potem próbowałem podejmowania podstawa LastUpdated wirtualne i przesłanianie go, utrzymując atrybut:

[Serializable] 
public class Record 
{ 
    public virtual DateTime LastUpdated {get; set; } 

    // other useful properties ... 
} 

public class EmployeeRecord : Record 
{ 
    public string EmployeeName {get; set; } 

    [XmlIgnore] 
    public override DateTime LastUpdated {get; set; } 
    // other useful properties ... 
} 

to nie działało. W obu próbach LastUpdated zignorował atrybut XmlIgnore i szczęśliwie przeszedł operację serializacji.

Czy istnieje sposób, aby to, co próbuję, miało miejsce?

+0

Jak serializujesz? Ponieważ jeśli używasz serializacji binarnej, atrybut XmlIgnore nie przyniesie wiele dobrego. –

+0

Używam XmlSerializer –

+0

Można użyć atrybutu NonSerialized do serializacji binarnej. – snarf

Odpowiedz

17

Po pierwsze, [Serializable] attr nie ma nic wspólnego z XmlSerializer. To jest czerwony śledź. [Serializable] ma znaczenie dla System.Runtime.Serialization, podczas gdy XmlSerializer funkcjonuje w System.Xml.Serialization. Jeśli dekorujesz swoją klasę [Serializable] i twoimi członkami za pomocą [XmlIgnore], prawdopodobnie pomylisz siebie lub innych czytelników twojego kodu.

XmlSerialization w .NET jest bardzo elastyczny. W zależności od tego, jak dokonuje się serializacji, bezpośrednio przez ciebie lub pośrednio, powiedzmy przez środowisko wykonawcze usług internetowych - masz różne sposoby kontrolowania rzeczy.

Jedną opcją jest użycie właściwości propertyName Określony wzór do włączania lub wyłączania właściwości w Serialization XML. Załóżmy, że masz ten kod:

public class TypeA 
{ 
    public DateTime LastModified; 
    [XmlIgnore] 
    public bool LastModifiedSpecified; 
} 

Następnie, jeśli jest fałszywe LastModifiedSpecified w instancji, pole LastModified nie zostanie odcinkach dla tej instancji. W konstruktorze swojego typu można ustawić LastModifiedSpecified, aby zawsze było prawdziwe w typie podstawowym, i zawsze było fałszywe w typie pochodnym. Właściwość boolean - LastModifiedSpecified - nigdy nie zostanie przekształcona do postaci szeregowej, ponieważ jest oznaczona jako XmlIgnore.

Ta mała sztuczka jest udokumentowana here.

Inną opcją jest użycie XmlAttributeOverrides, która jest sposobem dynamicznego dostarczania zestawu atrybutów serializacji XML (takich jak XmlElementAttribute, XmlIgnoreAttribute, XmlRootAttribute, i tak dalej ...) - dynamiczne dostarczanie tych atrybutów do serializera w środowisku wykonawczym . XmlSerializer, zamiast sprawdzać typ samego dla tych atrybutów, przejdzie po prostu przez listę nadpisań atrybutów dostarczonych do jej konstruktora.

var overrides = new XmlAttributeOverrides(); 
    // ....fill the overrides here.... 
    // create a new instance of the serializer specifying overrides 
    var s1 = new XmlSerializer(typeof(Foo), overrides); 
    // serialize as normal, here. 

Zostało to zilustrowane bardziej szczegółowo here.

W twoim przypadku możesz podać XmlIgnoreAttribute jako przesłonięcie, ale tylko przy serializacji typu pochodnego.(lub cokolwiek) Działa to tylko wtedy, gdy bezpośrednio tworzysz XmlSerializer - nie będzie działać, gdy serializacja jest wykonywana niejawnie przez środowisko wykonawcze, tak jak w przypadku usług internetowych.

Pozdrawiam!

+0

Wow, nigdy wcześniej nie słyszałem o tym Wzorze. Pracował jak urok! –

8

Najlepszym mogę myśleć ...

[Serializable] 
public class Record 
{ 
    public DateTime LastUpdated {get; set; } 
    public virtual bool ShouldSerializeLastUpdated() {return true;} 
    // other useful properties ... 
} 

public class EmployeeRecord : Record 
{ 
    public string EmployeeName {get; set; } 
    public override bool ShouldSerializeLastUpdated() {return false;} 
    // other useful properties ... 
} 

Zasadniczo istnieje kilka wzorów, które XmlSerializer względem; public bool ShouldSerialize*() i public bool *Specified {get;set;} (należy również oznaczyć *Specified za pomocą [XmlIgnore]).

Niezbyt elegancko, przyznam; ale XmlSerializer patrzy tylko na członków publicznych, więc nie możesz ich nawet ukryć (brakuje [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]).

Powiązane problemy