简体   繁体   English

如何使用接口类型化数组属性序列化对象?

[英]How to serialize object with interface typed array property?

I have an some XML that I wish to serialize and deserialize using the XmlSerializer . 我有一些XML,希望使用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. 我希望将来能够使用其他串行格式,例如JSON,YAML等,因此我从反序列化中得到的类应该共享相同的接口。

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? 创建XmlConfiguration对象时,XML反序列化操作如何知道使用XmlCommand具体类型?

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? 我想我可以在XmlConfiguration类中添加一个构造函数来分配一个具体类型的空数组,但是我不确定这是否可以按预期工作?

[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: 更新:我知道有XmlArrayItemAttribute属性可用,但是不确定它是否适用于接口:

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: 您仍然需要使用[XmlInclude]进行序列化以了解所有类型可能会发生的情况:

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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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