Игнорирование свойств в производных классах при использовании .NET XmlSerializer

У меня есть базовый класс с виртуальным свойством и производный тип, который переопределяет виртуальное свойство. Тип может быть сериализован в XML. Я пытаюсь НЕ сохранять свойство List of items, когда объект имеет производный тип. Чтобы добиться этого, производный класс украшает переопределенное свойство атрибутом [XmlIgnore]. К виртуальному свойству в базовом классе НЕ применяется атрибут XmlIgnore. По какой-то причине список элементов сериализуется каждый раз, даже если объект имеет производный тип (DynamicCart).

Когда я применяю атрибут XmlIgnore к виртуальному свойству в базовом классе, список не сериализуется в файл.

public class ShoppingCart
{  
   public virtual List<items> Items{get; set;}

   //and other properties 

   public void SerializeToXML (string filePath)
   {
     var xmlSerializer = new XmlSerializer(this.GetType());
     textWriter = new System.IO.StreamWriter(filePath);
     xmlSerializer.Serialize(textWriter, this);
     textWriter.Flush();
     textWriter.Close();  
   }
}

//A cart that is populated by algo based on parameters supplied by user. I have no need to
//persist the actual items across sessions.
class DynamicCart: ShoppingCart
{
   [XmlIgnore]
   public override List<items>{get;set;}
   //and other properties 
}

class Shop
{
   ShoppingCart cart = new DynamicCart();
   PopulateCart(cart);
   cart.serializeToXML(<PATH TO FILE>);
}

person Ken    schedule 11.03.2011    source источник
comment
Похоже, вы сами ответили на вопрос.   -  person Ondrej Tucny    schedule 11.03.2011
comment
Я реализовал обходной путь, но не ответил на мой вопрос, почему XMLSerializer не учитывает атрибут [XMLIgnore] в классе serived и не включает объект List ‹items› при сериализации DynamicCart?   -  person Ken    schedule 12.03.2011


Ответы (4)


Вы можете сделать это, добавив виртуальный ShouldSerialize*** метод к базовому классу. Например:

[XmlInclude(typeof(Sub))]
public class Base
{
    public virtual string Prop { get; set; }

    public virtual bool ShouldSerializeProp() { return true; }
}

public class Sub : Base
{
    public override string Prop { get; set; }

    public override bool ShouldSerializeProp() { return false; }
}

internal class Program
{
    private static void Main()
    {
        var o = new Sub { Prop = "Value" };

        var baseSer = new XmlSerializer(typeof (Base));
        var subSer = new XmlSerializer(typeof (Sub));

        Console.Out.WriteLine("BASE:");
        baseSer.Serialize(Console.Out, o);
        Console.Out.WriteLine();

        Console.Out.WriteLine("SUB:");
        subSer.Serialize(Console.Out, o);
        Console.Out.WriteLine();

        Console.ReadLine();
    }
}

Это производит (немного убранно):

BASE:
<Base xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Sub">
  <Prop>Value</Prop>
</Base>

SUB:
<Sub />

Метод должен включать точное имя рассматриваемого свойства после ShouldInclude....

person Drew Noakes    schedule 24.07.2015

Я думаю, что ваш сериализатор использует ваш базовый класс вместо производного.

public void SerializeToXML(string filePath, Type type)
{
    xmlSerializer = new XmlSerializer(type);
    textWriter = new System.IO.StreamWriter(filePath);
    xmlSerializer.Serialize(textWriter, this);
    textWriter.Flush();
    textWriter.Close();
}

class Shop
{
    ShoppingCart cart= new DynamicCart();
    PopulateCart(cart);
    cart.serializeToXML(<PATH TO FILE>, typeof(DynamicCart));
}
person loupceuxl    schedule 15.08.2012

Я думаю, вам нужно объявить производный тип в базовом классе для сериализации XML. Звучит немного глупо, но это по спецификации.

См. Эту страницу MSDN и найдите следующий пример:

[System.Xml.Serialization.XmlInclude( typeof( Derived ) )]
public class Base
{
    // ...
}
person Marcel    schedule 11.03.2011
comment
Добавление этого атрибута в класс проблему не решило. Сериализатор продолжал сериализовать List ‹Items›, даже несмотря на то, что переопределенное свойство в производном классе имело атрибут [XMLIgnore]. Я наконец закончил; удаление переопределенного свойства из производного класса; и написание логики условной сериализации в базовом классе для применения атрибута XMLIgnore, если производный класс сериализуется. - person Ken; 12.03.2011
comment
Любая подсказка относительно того, почему серилизатор не учитывает атрибут [XMLIgnore] в моем производном классе? - person Ken; 12.03.2011

Попробуй это

  XmlSerializer serializer = new XmlSerializer(typeof(DynamicCart), new Type[]{typeof(ShoppingCart)});

это позволит вам добавить столько типов, сколько вы хотите включить в сериализатор.

person BreakHead    schedule 11.03.2011