C# 在对聚合某个类的另一个类进行序列化期间排除该类的某些属性

C# 在对聚合某个类的另一个类进行序列化期间排除该类的某些属性,c#,.net,xml,C#,.net,Xml,我正在使用XmlSerializer。一个大类实例正在被序列化,而那个大类实例聚合(我想说它几乎拥有)较小的类,并涉及一些继承。似乎在基类中,某些属性是至关重要的,用于在序列化时镜像它们的状态。但是对于它们的一些子类,这些属性应该被抑制,因为添加了其他更可读的属性 下面是一个示例(不是真正的代码示例): 输出仍然包含这两种类型的x属性。列表通过引用适当的子类来包含它们,所以它不像XmlSerializer看不到它们的实际类。尽管有覆盖,但示例xml输出如下所示 <?xml version=

我正在使用XmlSerializer。一个大类实例正在被序列化,而那个大类实例聚合(我想说它几乎拥有)较小的类,并涉及一些继承。似乎在基类中,某些属性是至关重要的,用于在序列化时镜像它们的状态。但是对于它们的一些子类,这些属性应该被抑制,因为添加了其他更可读的属性

下面是一个示例(不是真正的代码示例):

输出仍然包含这两种类型的
x
属性。
列表通过引用适当的子类来包含它们,所以它不像
XmlSerializer
看不到它们的实际类。尽管有覆盖,但示例xml输出如下所示

<?xml version="1.0" encoding="utf-8"?>
<BigClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <List1>
    <Derived1>
      <x>1</x>
      <!-- other stuff -->
    </Derived1>
  </List1>
  <List2>
    <Derived2>
      <x>2</x>  <!-- unwanted guy -->
      <y>20</y>
      <!-- other stuff -->
    </Derived2>
  </List2>
  <!-- other stuff -->
</BigClass>
似乎无法修复它。在聚合层次结构中,实际上有更多的节点,从
BigClass
Derived1/2
。将它们全部从
Derived2
添加到根目录没有帮助。所以我假设这个建议即使在这个简化的情况下也不能解决它。(更新2。它不会)

(免责声明。有些人可能会说,序列化字段类似于所讨论的类的公共接口,因此将它们隐藏在派生类中有点代码味道。但我不会在这里讨论接口含义,只有实现上述目标的方法。)

XmlSerializer
有两个功能,允许从输出文件中排除某些属性:

  • 指定的
    模式(也称为旧模式),例如,如:
  • 应该序列化()
    模式,例如:
  • 在删除继承树中的冗余字段方面,两者都有一些优点和缺点。让我们看看:

    指定的
    模式。用法:

    public class Example
    {
        public int x { get; set; }
    
        [XmlIgnore]
        public bool xSpecified;
    
        public Example()
        {
            xSpecified = <set your value for this class>;
        }
    }
    
    public class Example
    {
        public int x { get; set; }
    
        public virtual bool ShouldSerializex()
        {
            return <your logic expression here>;
        }
    }
    
    公共类示例
    {
    公共整数x{get;set;}
    [XmlIgnore]
    指定的公共布尔值;
    公共示例()
    {
    xsspecified=;
    }
    }
    
    优点:

    • 如果逻辑需要,可以在其他类中设置
    缺点:

    • 破坏所讨论类的封装
    • 有助于对象在内存中的大小,每个对象每个属性一个布尔值
    • 您必须记住将其设置为适当的值,例如在构造函数中
    应该序列化()
    模式。用法:

    public class Example
    {
        public int x { get; set; }
    
        [XmlIgnore]
        public bool xSpecified;
    
        public Example()
        {
            xSpecified = <set your value for this class>;
        }
    }
    
    public class Example
    {
        public int x { get; set; }
    
        public virtual bool ShouldSerializex()
        {
            return <your logic expression here>;
        }
    }
    
    公共类示例
    {
    公共整数x{get;set;}
    公共虚拟bool应序列化x()
    {
    返回;
    }
    }
    
    优点:

    • 保持类的封装,允许包含逻辑
    • 每个属性没有额外的内存
    • 总体上更灵活
    缺点:

    • 在这种情况下,必须使其成为虚拟的,以便它也可以与派生类一起工作,因此可能需要为每个对象中的vtable指针提供额外的内存

    对于我的特殊问题,我在不同的地方使用了这两种方法。需要隐藏多个属性的自给自足类可以从#2中获得更多优势,特别是当项目有大量实例的列表时。小类曾经是组成大类的“砖石”,可能“愚蠢”到不知道是否序列化某些内容,这使得#1成为一种可能的选择。

    我不完全确定,但我认为这是正确的:
    重写.Add(typeof(List),“x”,ignore)但是,我不确定这是否有效,因为typeof()将返回泛型集合…@MaxOvrdrv实际情况下有更多的“深度”。我添加了一些代码,比如
    overrides.Add(typeof(List),“x”,ignore)对于我要“向上”聚合层次结构的每个节点,但它没有帮助。我将更新问题说明。其他问题的说明可能会有所帮助。它提到了附加属性
    XmlArrayAttribute
    XmlArrayItemAttribute
    @dialogicus
    XmlArrayItemAttribute
    有八个属性,但我不明白更改节点名称、名称空间、类型、类型ID等在这里有什么帮助。。。请你详细说明一下好吗?我也不知道。对我来说,这就像一条通往解决之路。这就是我为什么写评论而不是回答的原因。
    public class Example
    {
        public int x { get; set; }
    
        public virtual bool ShouldSerializex()
        {
            return <your logic expression here>;
        }
    }