简体   繁体   中英

How to serialize object with interface typed array property?

I have an some XML that I wish to serialize and deserialize using the XmlSerializer . I wish to be able to possibly use other serial formats in the future, such as JSON, YAML, etc, so my resulting classes from deserialization should share the same interface.

However, my interface contains an array of objects that also use an interface:

public interface IConfiguration
{
    ICommand[] Commands { get; set; }
}

public Interface ICommand
{
    // Command properties
}

[System.SerializableAttribute()]
public XmlConfiguration : IConfiguration
{
    ICommand[] Commands { get; set; }
}

[System.SerializableAttribute()]
public XmlCommand : ICommand
{
    // Command properties
}

How will the XML deserialize operation know to use the XmlCommand concrete type when creating the XmlConfiguration object?

Thinking as I type...

I guess I could add a constructor to the XmlConfiguration class to assign an empty array of the concrete type, but I am not sure if this would work as intended?

[System.SerializableAttribute()]
class XmlConfiguration : IConfiguration
{
    public XmlConfiguration()
    {
        Commands = new XmlCommand[] { };
    }
}

Update: I realize there is the XmlArrayItemAttribute attribute available, unsure if it will work for interfaces though:

class XmlConfiguration : IConfiguration
{
    [System.Xml.Serialization.XmlArrayItemAttribute(typeof(XmlCommand))]
    public ICommand[] Commands { get; set; }
}

Update: I can probably also do:

class XmlConfiguration : IConfiguration
{
    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public ICommand[] Command
    {
        get => CommandsConcrete;
        set => CommandsConcrete = (XmlCommand[])value;
    }

    [System.Xml.Serialization.XmlElementAttribute(ElementName = "Commands")]
    public XmlCommand[] CommandsConcrete { get; set; }
}

To serialize interface property one easy possibility is to use another property. You still need to use [XmlInclude] for serializer to know all types what may occurs:

public interface ICommand
{
    string Text { get; set; }
}

public class CommandA : ICommand
{
    public string Text { get; set; }
}

public class CommandB : ICommand
{
    public string Text { get; set; }
}

[XmlInclude(typeof(CommandA))]
[XmlInclude(typeof(CommandB))]
public class Settings
{
    [XmlIgnore]
    public ICommand[] Commands { get; set; }

    [XmlArray(nameof(Commands))]
    public object[] CommandsSerialize
    {
        get { return Commands; }
        set { Commands = value.Cast<ICommand>().ToArray(); }
    }
}

Upon serialization this will produce

xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Commands>
    <anyType xsi:type="CommandA">
      <Text>a</Text>
    </anyType>
    <anyType xsi:type="CommandB">
      <Text>b</Text>
    </anyType>
  </Commands>
</Settings>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM