使用 .NET 的 XmlSerializer 时忽略派生类的属性

发布于 2024-10-21 14:54:51 字数 1069 浏览 1 评论 0原文

我有一个带有虚拟属性的基类和一个重写虚拟属性的派生类型。该类型可以序列化为 XML。我想做的不是当对象属于派生类型时保留项目属性列表。为了实现此目的,派生类使用 [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>);
}

I have a base class with a virtual property and a derived type that overrides the virtual property. The type can be serialized to XML. What I am trying to do is NOT to persist the List of items property when the object is of the derived type. To acheive this the derived class decorates the overridden property with the [XmlIgnore] attribute. The virtual property in the base class does NOT apply XmlIgnore attribute. For some reason the List of items get serialized every even when the object is of the derived type (DynamicCart).

When I apply XmlIgnore attribute to the virtual property in the base class the list does not get serialized to file.

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>);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

如若梦似彩虹 2024-10-28 14:54:51

您可以通过向基类添加虚拟 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... 之后包含要考虑的属性的确切名称。

You can do this by adding a virtual ShouldSerialize*** method to the base class. For example:

[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();
    }
}

This produces (tidied slightly):

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

SUB:
<Sub />

The method must have include the exact name of the property to consider after ShouldInclude....

伊面 2024-10-28 14:54:51

我认为您的序列化程序正在使用您的基类而不是派生类。

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));
}

I think your serializer is using your base class instead of the derived.

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));
}
小ぇ时光︴ 2024-10-28 14:54:51

如果我理解得很好,您要做的就是有损转换为基类,也称为 切片(至少在 C++ 中)。

如果您有能力将课程变成 records (我相信是这种情况),代码非常简单,因为您可以使用基础的合成复制构造函数。

public record ShoppingCart
{
    public virtual List<item> Items
    {
        get;
        set;
    }

    //and other properties 
    public void SerializeToXML(string filePath)
    {
        var xmlSerializer = new XmlSerializer(typeof(ShoppingCart)); // type needs to be fixed here
        textWriter = new System.IO.StreamWriter(filePath);
        xmlSerializer.Serialize(textWriter, new ShoppingCart(this)); // synthesized copy constructor
        textWriter.Flush();
        textWriter.Close();  
    }
}

其余代码仍然保留。看一下稍微修改过的演示,在工作中看到它

If I understand well, what you're trying to do is a lossy conversion to base class also called slicing (at least in C++).

If you can afford to turn your classes into records (which is the case, I believe), the code is pretty straightforward, as you can use the synthesized copy constructor of the base.

public record ShoppingCart
{
    public virtual List<item> Items
    {
        get;
        set;
    }

    //and other properties 
    public void SerializeToXML(string filePath)
    {
        var xmlSerializer = new XmlSerializer(typeof(ShoppingCart)); // type needs to be fixed here
        textWriter = new System.IO.StreamWriter(filePath);
        xmlSerializer.Serialize(textWriter, new ShoppingCart(this)); // synthesized copy constructor
        textWriter.Flush();
        textWriter.Close();  
    }
}

The rest of the code remains. Take a look at a slightly modified demo to see it at work.

冷情妓 2024-10-28 14:54:51

我想您需要在基类中声明派生类型以进行 XML 序列化。听起来有点傻,但这是按照规范的。

请参阅此 MSDN 页面,并查找以下示例:

[System.Xml.Serialization.XmlInclude( typeof( Derived ) )]
public class Base
{
    // ...
}

I guess you need to declare the derived type in the base class for XML serialization. Sounds a bit silly, but is by specification.

See this MSDN page, and look for the following example:

[System.Xml.Serialization.XmlInclude( typeof( Derived ) )]
public class Base
{
    // ...
}
甜妞爱困 2024-10-28 14:54:51

尝试一下,

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

这将允许您添加尽可能多的类型,您希望序列化程序包含在内。

Try this

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

this will allow you to add as many types, you want serializer to inclusde.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文