XMLIgnore:从子类节点中删除基类属性

时间:2014-08-27 12:16:47

标签: c# xml-serialization xmlserializer

我正在使用XMLIgnore属性来删除序列化中不需要的属性。但是我想从子类中删除一些基类属性。我想从基类中获取属性,但不应在子类节点中重复。

是否可以从子类节点中删除基类属性?

在我的代码中,我得到格式以下的输出:当我通过XMLIgnore从基类中删除属性时。

<?xml version="1.0" encoding="utf-8"?>
<InformationCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <projects>
    <Project xsi:type="Group">
      <GroupName>Accounts</GroupName>
      <Comment>Financial Transaction</Comment>
    </Project>
  </projects>
</InformationCollection>

但实际上我希望输出低于格式

<?xml version="1.0" encoding="utf-8"?>
<InformationCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <projects>  
      <ProjectId>1</ProjectId>
      <ProjectName>HRMS</ProjectName>
      <Project xsi:type="Group">
         <GroupName>Accounts</GroupName>
         <Comment>Financial Transaction</Comment>
    </Project>
  </projects>
</InformationCollection>

我正在尝试以下代码:

[XmlInclude(typeof(Group))]
    public class Project
    {
        public int ProjectId { get; set; }
        public string ProjectName { get; set; }
        public Project() { }
        public Project(int projectId, string projectName)
        {
            ProjectId = projectId;
            ProjectName = projectName;
        }
    }
    public class Group : Project
    {        
        public string GroupName;        
        public string Comment;
        public Group():base() { }
        public Group(int projectId, string projectName)
            : base(projectId, projectName)
        {

        }
        public Group(int projectId, string projectName, string groupName, string comment)
            : this(projectId, projectName)
        {
            GroupName = groupName;
            Comment = comment;
        }
    }
    public class InformationCollection
    {
        public List<Project> projects = new List<Project>();
        public InformationCollection()
        {
            projects.Add(new Group(1,"HRMS","Accounts","Financial Transaction"));
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            SerializeObject("IgnoreXml.xml");
        }

        public static XmlSerializer CreateOverrider()
        {
            XmlAttributeOverrides xOver = new XmlAttributeOverrides();
            XmlAttributes attrs = new XmlAttributes();
            attrs.XmlIgnore = true;
            xOver.Add(typeof(Project), "ProjectName", attrs);
            xOver.Add(typeof(Project), "ProjectId", attrs);
            XmlSerializer xSer = new XmlSerializer(typeof(InformationCollection), xOver);
            return xSer;
        }

        public static void SerializeObject(string filename)
        {
            try
            {
                XmlSerializer xSer = CreateOverrider();
                InformationCollection informationCollection = new InformationCollection();                
                TextWriter writer = new StreamWriter(filename);
                xSer.Serialize(writer, informationCollection);
                writer.Close();
            }
            catch (Exception ex)
            {
                throw;
            }
        }
    }

1 个答案:

答案 0 :(得分:1)

假设您已控制基类和派生类,可以通过为要为其控制输出的每个属性XmlSerializer添加虚拟bool ShouldSerializeXXX()方法,使用XXX执行此操作。在基类中,make方法应该返回true,并且在派生类中,应该重写它以返回false

例如,假设您只想在派生类中禁止Id属性的序列化,您可以这样做:

public class BaseClass
{
    public int Id { get; set; }

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

public class DerivedFromBaseClass : BaseClass
{
    public override bool ShouldSerializeId()
    {
        return false;
    }
}

然后,测试:

    public static void TestSuppressingPropertyInDerivedClass()
    {
        var baseClass = new BaseClass() { Id = 31 };
        var derivedClass = new DerivedFromBaseClass { Id = 31 };

        var baseXml = baseClass.GetXml();
        // Xml looks like 

        Debug.Assert(baseXml.Contains("Id")); // No assert
        var derivedXml = derivedClass.GetXml();
        Debug.Assert(!derivedXml.Contains("Id")); // no assert.
    }

BaseClass的输出XML如下所示:

<?xml version="1.0" encoding="utf-16"?>
<BaseClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <Id>31</Id>
</BaseClass>

对于DerivedFromBaseClass

<?xml version="1.0" encoding="utf-16"?>
<DerivedFromBaseClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />

正如您所看到的,Id仅在派生类的XML中被抑制,我认为,这就是您要求的内容。

但是,不过,我认为你的对象模型可能并不理想。如果基类中的属性不应出现在派生类中,则表明您应该提取更通用的抽象基类:

public abstract class AbstractProject {
{
    // Properties common to "Group" and "Project"
}

public class Project : AbstractProject {
{
    // Properties specific to Project
}

public class Group : AbstractProject {
{
    // Properties specific to Group
}