2009-02-26 2 views
10

Я пытаюсь найти способ изменить поведение сериализации свойства.Переопределение свойства с атрибутом

Допустит, у меня есть такая ситуация:

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

    // other useful properties ... 
} 

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

    // other useful properties ... 
} 

Теперь я хочу сериализацию EmployeeRecord. Я не хочу, чтобы свойство LastUpdated из класса Record было сериализовано. (Я хочу, чтобы LastUpdated был сериализован, когда я сериализую запись, хотя).

Сначала я пытался прятать LastUpdated собственность, используя новый ключевое слово, а затем добавить атрибут XmlIgnore:

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

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

Но это не сработало. Затем я попытался сделать основание LastUpdated виртуальной и опрокинув его, сохраняя атрибут:

[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 ... 
} 

Это не сработало. В обеих попытках LastUpdated проигнорировал атрибут XmlIgnore и с радостью занялся сериализацией.

Есть ли способ сделать то, что я пытаюсь сделать?

+0

Как вы его сериализуете? Потому что, если вы используете двоичную сериализацию, атрибут XmlIgnore не принесет много пользы. –

+0

Я использую XmlSerializer –

+0

Вы должны использовать атрибут NonSerialized для двоичной сериализации. – snarf

ответ

17

Во-первых, [Serializable] attr не имеет ничего общего с XmlSerializer. Это красная сельдь. [Serializable] имеет смысл для System.Runtime.Serialization, а XmlSerializer - в System.Xml.Serialization. Если вы украшаете свой класс с помощью [Serializable] и ваших членов с помощью [XmlIgnore], вы, вероятно, путаете себя или других читателей вашего кода.

XmlSerialization in .NET очень гибкий. В зависимости от того, как выполняется сериализация, прямо или косвенно, скажем, во время выполнения веб-сервисов - у вас есть разные способы управления вещами.

Один из вариантов заключается в использовании свойства Name Указанный шаблон для включения или выключения объекта в XML-сериализации. Предположим, у вас есть этот код:

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

Тогда, если LastModifiedSpecified ложна в экземпляре, то LastModified поле не будет сериализован для этого экземпляра. В конструкторе для вашего типа вы можете установить LastModifiedSpecified, чтобы всегда быть истинным в базовом типе и всегда false в производном типе. Фактическое значение boolean - LastModifiedSpecified - никогда не становится сериализованным, потому что оно отмечено XmlIgnore.

Этот небольшой трюк задокументирован here.

Другой вариант заключается в использовании XmlAttributeOverrides, что является способом динамического предоставления набора атрибутов XML сериализации (как XmlElementAttribute, XmlIgnoreAttribute, XmlRootAttribute, и так далее ...) - динамически обеспечивающий эти атрибуты сериализатором во время выполнения , XmlSerializer вместо проверки самого типа для этих атрибутов просто просматривает список атрибутов переопределения, предоставляемых его конструктору.

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. 

Это показано более подробно here.

В вашем случае вы должны предоставить XmlIgnoreAttribute в качестве переопределения, но только при сериализации производного типа.(или что-то еще). Это работает только тогда, когда вы непосредственно создаете экземпляр XmlSerializer - это не сработает, если сериализация будет выполняться неявно с помощью среды выполнения, как с веб-службами.

Cheers!

+0

Ничего себе, я даже не слышал о заданном шаблоне раньше. Работал как шарм! –

8

Лучшее, что я могу думать ...

[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 ... 
} 

В принципе, есть несколько моделей, которые XmlSerializer уважает; public bool ShouldSerialize*() и public bool *Specified {get;set;} (обратите внимание, что вы должны отметить *Specified с [XmlIgnore] тоже ...).

Не очень элегантный, я дам; но XmlSerializer смотрит только на публичных пользователей, поэтому вы даже не можете их скрыть (за исключением [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]).

Смежные вопросы