我如何通过app.config或web全局指定DataContractSerializer EmitDefaultVal

本文关键字:全局 DataContractSerializer EmitDefaultVal web 何通过 app config | 更新日期: 2023-09-27 18:02:13

我有一个非常大的类库,有>100个POCO对象。我需要将这些对象序列化为XML,以传输到REST服务。

我一直在尝试使用DataContractSerializer,但它输出具有i:nil="true"的XML元素,用于任何为空的属性。这会触发我正在向其传输XML的REST服务。是的,我知道不应该。服务提供商告诉我,纠正这个问题需要几个月的时间。我没有几个月的时间来等待这项服务的工作。

我一直在挖掘文档,试图找到一种方法来抑制这些nil对象的传输。我知道我可以将每个POCO对象的每个单独属性的EmitDefaultValue属性设置为false。我不会为超过100个对象这么做,除非我别无选择。此外,我认为不应该强迫我用DataContract属性注释类库对象。我也不想用dataconcontractsurrogate镜像我的类库。

当然,在某个地方有一个配置选项,我可以指定序列化的默认行为应该是EmitDefaultValue = false。但我一直找不到。我希望其他人已经找到了它,或者已经找到了另一个全局选项来从XML中抑制null属性。

  • 可以在app.config/web.config中指定吗?
  • 或者可以在DataContractSerializer实例上设置?

如果这个不存在,这似乎是微软的一个巨大疏忽。

我如何通过app.config或web全局指定DataContractSerializer EmitDefaultVal

我相信没有官方的方法来全局设置这个属性,可能是因为在大多数情况下它被描述为不推荐的做法。

但是有一个解决方法。您可以在System.Runtime.Serialization名称空间中定义自己的DataMemberAttribute,默认情况下将EmitDefaultValue设置为false。把它放在你项目的某个地方。这就是你所要做的。编译器会给你一个警告,说你的类型与导入的类型冲突,但最终还是会使用你的类型。我从微软源码中获取了这个类,将EmitDefaultValue设置为false,并替换异常抛出顺序检查,因为它使用内部实用程序类:

namespace System.Runtime.Serialization
{
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
    public sealed class DataMemberAttribute : Attribute
    {
        string name;
        bool isNameSetExplicitly;
        int order = -1;
        bool isRequired;
        bool emitDefaultValue = false;
        public string Name
        {
            get { return name; }
            set { name = value; isNameSetExplicitly = true; }
        }
        public bool IsNameSetExplicitly
        {
            get { return isNameSetExplicitly; }
        }
        public int Order
        {
            get { return order; }
            set
            {
                if (order < 0)
                    throw new InvalidDataContractException();
                order = value;
            }
        }
        public bool IsRequired
        {
            get { return isRequired; }
            set { isRequired = value; }
        }
        public bool EmitDefaultValue
        {
            get { return emitDefaultValue; }
            set { emitDefaultValue = value; }
        }
    }
}

现在如果我们取new Foo():

using System.Runtime.Serialization;
namespace FooBar
{
    [DataContract]
    public class Foo
    {
        // Warning about type conflict.
        [DataMember]
        public string Bar { get; set; }
    }
}

它将被DataContractSerializer序列化为:

<Foo xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication1"
     xmlns:i="http://www.w3.org/2001/XMLSchema-instance"/>