How to dynamically select which inherited properties will be serialized?

I have a base class with several properties and three classes that are produced.

I want to serialize an object containing all three derived classes, but each derived class must expose a different set of properties from the base class.

I want to do this dynamically using XmlAttributeOverrides and have tried several different ways to do this, but it does nothing.

[Serializable]
public class A
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
}

[Serializable]
public class B : A
{
}

[Serializable]
public class C : A
{
}

[Serializable]
public class Container
{
    public B B { get; set; }
    public C C { get; set; }
}


class Program
{
    static void Main(string[] args)
    {
        MemoryStream memoryStream = new MemoryStream();
        StreamWriter encodingWriter = new StreamWriter(memoryStream, Encoding.Unicode);

        var xmlWriter = XmlWriter.Create(encodingWriter, new XmlWriterSettings
        {
            Indent = false,
            OmitXmlDeclaration = true,
        });
        XmlAttributeOverrides overrides = new XmlAttributeOverrides();
        XmlAttributes attribute = new XmlAttributes();
        attribute.XmlIgnore = true;
        overrides.Add(typeof(B), "Property1", attribute);
        overrides.Add(typeof(C), "Property2", attribute);
        var container = new Container
            {
                B = new B {Property1 = "B property 1", Property2 = "B property 2"},
                C = new C {Property1 = "C property 1", Property2 = "C property 2"}
            };

        var xmlSerializer = new XmlSerializer(typeof(Container), overrides);
        xmlSerializer.Serialize(xmlWriter, container);

        var result = Encoding.Unicode.GetString(memoryStream.ToArray());
    }
}

In the above code, the result string will contain all properties A in B and C, but I really want it to just contain B Property2 and C Property1 (since I set the XmlIgnore attributes for them).

How to do it?

EDIT: expected XML:

<Container xmlns:xsd="http://www.w3.org/2001/XMLSchema"    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B><Property2>B property 2</Property2></B><C><Property1>C property 1</Property1></C></Container>

Actual XML:

<Container xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><B><Property1>B property 1</Property1><Property2>B property 2</Property2></B><C><Property1>C property 1</Property1><Property2>C property 2</Property2></C></Container>

EDIT 2: , , .

Container- (, ), (, ). Container , , - ( -).

XmlAttributeOverrides XmlIgnore . ( ), - ().

, Property1 B Property2 C, , XML . ; , XmlSerializer A, , B C.

+4
1

, , XML , , , . (EDIT: , , XML-)

ShouldSerializePROPERTYNAME XmlSerializer . :

public class A
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }

    public virtual bool ShouldSerializeProperty1()
    {
        return true;
    }

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

:

public class B : A
{
    public override bool ShouldSerializeProperty1()
    {
        return false;
    }
}

public class C : A
{
    public override bool ShouldSerializeProperty2()
    {
        return false;
    }
}

, , Container:

public class A
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }

    [XmlIgnore]
    internal bool _ShouldSerializeProperty1 = true;
    [XmlIgnore]
    internal bool _ShouldSerializeProperty2 = true;

    public bool ShouldSerializeProperty1()
    {
        return _ShouldSerializeProperty1;
    }

    public bool ShouldSerializeProperty2()
    {
        return _ShouldSerializeProperty2;
    }
}

B C Container :

public class Container
{
    private B _B;
    public B B 
    { 
        get
        {
            return _B;
        }
        set
        {
            if (value != null)
            {
                value._ShouldSerializeProperty1 = false;
                value._ShouldSerializeProperty2 = true;
            }
            _B = value;
        }
    }

    private C _C;
    public C C
    {
        get
        {
            return _C;
        }
        set
        {
            if (value != null)
            {
                value._ShouldSerializeProperty1 = true;
                value._ShouldSerializeProperty2 = false;
            }
            _C = value;
        }
    }
}

( , ), , ShouldSerialize. , , , .

EDIT: , , , DRY ( , ).

A virtual :

public class A
{
    public virtual string Property1 { get; set; }
    public virtual string Property2 { get; set; }
}

public class B : A
{
    public override string Property1 { get { return base.Property1; } set { base.Property1 = value; } }
    public override string Property2 { get { return base.Property2; } set { base.Property2 = value; } }
}

public class C : A
{
    public override string Property1 { get { return base.Property1; } set { base.Property1 = value; } }
    public override string Property2 { get { return base.Property2; } set { base.Property2 = value; } }
}

, ( ), / XmlSerializer , XmlIgnore :

overrides.Add(typeof(A), "Property1", attribute);
overrides.Add(typeof(A), "Property2", attribute);

XmlIgnore , :

overrides.Add(typeof(B), "Property2", attribute);
overrides.Add(typeof(C), "Property1", attribute);

.

+5

Source: https://habr.com/ru/post/1532675/


All Articles