XML serialization of interface property

2019-01-02 17:00发布

I would like to XML serialize an object that has (among other) a property of type IModelObject (which is an interface).

public class Example
{
    public IModelObject Model { get; set; }
}

When I try to serialize an object of this class, I receive the following error:
"Cannot serialize member Example.Model of type Example because it is an interface."

I understand that the problem is that an interface cannot be serialized. However, the concrete Model object type is unknown until runtime.

Replacing the IModelObject interface with an abstract or concrete type and use inheritance with XMLInclude is possible, but seems like an ugly workaround.

Any suggestions?

9条回答
何处买醉
2楼-- · 2019-01-02 17:55

If you know your interface implementors up-front there's a fairly simple hack you can use to get your interface type to serialize without writing any parsing code:

public interface IInterface {}
public class KnownImplementor01 : IInterface {}
public class KnownImplementor02 : IInterface {}
public class KnownImplementor03 : IInterface {}
public class ToSerialize {
  [XmlIgnore]
  public IInterface InterfaceProperty { get; set; }
  [XmlArray("interface")]
  [XmlArrayItem("ofTypeKnownImplementor01", typeof(KnownImplementor01)]
  [XmlArrayItem("ofTypeKnownImplementor02", typeof(KnownImplementor02)]
  [XmlArrayItem("ofTypeKnownImplementor03", typeof(KnownImplementor03)]
  public object[] InterfacePropertySerialization {
    get { return new[] { InterfaceProperty } }
    set { InterfaceProperty = (IInterface)value.Single(); }
  }
}

The resulting xml should look something along the lines of

 <interface><ofTypeKnownImplementor01><!-- etc... -->
查看更多
余生请多指教
3楼-- · 2019-01-02 17:56

Unfortunately there's no simple answer, as the serializer doesn't know what to serialize for an interface. I found a more complete explaination on how to workaround this on MSDN

查看更多
心情的温度
4楼-- · 2019-01-02 18:01

You can use ExtendedXmlSerializer. This serializer support serialization of interface property without any tricks.

var serializer = new ConfigurationContainer().UseOptimizedNamespaces().Create();

var obj = new Example
                {
                    Model = new Model { Name = "name" }
                };

var xml = serializer.Serialize(obj);

Your xml will look like:

<?xml version="1.0" encoding="utf-8"?>
<Example xmlns:exs="https://extendedxmlserializer.github.io/v2" xmlns="clr-namespace:ExtendedXmlSerializer.Samples.Simple;assembly=ExtendedXmlSerializer.Samples">
    <Model exs:type="Model">
        <Name>name</Name>
    </Model>
</Example>

ExtendedXmlSerializer support .net 4.5 and .net Core.

查看更多
登录 后发表回答