【问题标题】:Serialize a type with XmlSerializer by omitting it when it has a null field使用 XmlSerializer 序列化一个类型,当它有一个空字段时省略它
【发布时间】:2015-12-06 07:17:28
【问题描述】:

这是一个独立的示例程序来演示我的问题:https://gist.github.com/jennings/46c20733df559d02b9ad

我正在编写一个类型 Maybe<T>,它看起来像这样:

public struct Maybe<T> : IXmlSerializable where T : class
{
    readonly T _value;
    //...
}

我可以完成这两个序列化目标之一吗?

  1. 如果Maybe&lt;T&gt; 类型的属性正在被序列化,如果其_value 为空,则根本不发出该属性(字符串属性似乎有这种行为)。

  2. 序列化_value就位Maybe&lt;T&gt;

所以如果使用我的类型的类看起来像这样:

public class AnyRandomObjectUsingMyType
{
    public Maybe<string> MaybeAString{ get; set; }
}

那么如果MaybeaString._value 为空,我在序列化时想要这个:

<AnyRandomObjectUsingMyType>
</AnyRandomObjectUsingMyType>

想要以下任何一种:

<AnyRandomObjectUsingMyType>
  <MaybeAString xsi:nil="true" />
</AnyRandomObjectUsingMyType>

<AnyRandomObjectUsingMyType>
  <MaybeAString></MaybeAString>
</AnyRandomObjectUsingMyType>

我不想在AnyRandomObjectUsingMyType上配置序列化,因为会有很多很多。我宁愿让Maybe&lt;T&gt; 控制它,这样到处都能得到相同的行为。


一些上下文

Maybe&lt;T&gt; 类型用于替代T。但是我们在几个地方使用了 XML 序列化。如果有这样的对象:

// Version 1 class
public class SomethingBeingSerialized
{
    public string SomeValue { get; set; }
}

当 SomeValue 为 null 时,此类序列化为:

<SomethingBeingSerialized>
</SomethingBeingSerialized>

我希望能够将课程更改为:

// Version 2 class
public class SomethingBeingSerialized
{
    public Maybe<string> SomeValue { get; set; }
}

而且我希望序列化的表示是相同的。如果 V1 应用程序反序列化,它会得到一个空字符串。如果 V2 应用反序列化,它会得到一个 Maybe&lt;string&gt;,它代表 None。

我已经尝试在我的 IXmlSerializable.WriteXml 方法中执行此操作,但是当它被调用时,XmlWriter 似乎已经向它的底层流写入了这么多内容:

<SomeValue 

所以当我的WriteXml 方法被调用时,似乎为时已晚。也许还有另一种方法来控制它?

如果我可以向序列化程序指定:“一旦遇到Maybe&lt;T&gt; 类型的对象,就序列化它的_value 属性来代替Maybe&lt;T&gt;”,这也将实现我的目标。

【问题讨论】:

    标签: c# serialization ixmlserializable


    【解决方案1】:

    不要让 Maybe 可序列化,而是让它成为容器可序列化。您可以为 Maybe 提供一个扩展方法,根据需要为它的值构建一个 XML 节点,并且在被序列化的类中将包含扩展方法的返回值。

    public static class MaybeMethods
    {
        public static string SerializeValue<T>(this Maybe<T> source)
        {
             // Do the work to serialize the value in Maybe
        }
    }
    

    在您的托管类的序列化方法中

    public void WriteXml(XmlWriter writer)
    {
         var maybeXml = myMaybe.SerializeValue();
    
         // if maybeXml is not null, include it in your writer
    }
    

    【讨论】:

    • 我知道我可以控制容器上的序列化,但我不想这样做,因为会有很多很多。我宁愿让Maybe&lt;T&gt; 控制它,这样每个容器类都会获得相同的行为。
    猜你喜欢
    • 1970-01-01
    • 2016-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多