0

I am using XMLIgnore property to remove unwanted properties at serialization. But I want to remove some base class property from child class only. I want property from base class but it should not repeat in child class node.

Is it possible to remove base class properties from child class nodes?

In my code I am getting output below format: When I am removing property from base class through 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>

But actually I am expecting output below Format

<?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>

I am trying this by below code:

[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;
            }
        }
    }
Sam
  • 433
  • 1
  • 10
  • 26

1 Answers1

1

Assuming you have control of both the base and derived classes, you can do this with XmlSerializer by adding a virtual bool ShouldSerializeXXX() method for each property XXX for which you wish to control output. In the base class, make method should return true, and in the derived class, it should be overridden to return false.

For instance, say you want to suppress serialization of the Id property in a derived class only, you can do:

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

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

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

And then, to test:

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

The output XML for the BaseClass looks like:

<?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>

And for 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" />

As you can see, Id has been suppressed in the XML for the derived class only, which is, I think, what you are requesting.

As an aside, however, I think your object model here may not be ideal. If you have properties in the base class that should not appear in a derived class, that suggests you should extract a more general, abstract base class:

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
}
dbc
  • 104,963
  • 20
  • 228
  • 340