如何通过app.config或web.config或其他方式全局指定DataContractSerializer EmitDefaultValue = false?

cru*_*ush 9 c# xml asp.net

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

我一直在尝试使用DataContractSerializer,但它i:nil="true"为任何null属性输出XML元素.这使我正在传输XML的REST服务运行起来.是的,我意识到它不应该.服务提供商告诉我,纠正这个问题需要几个月的时间.我没有几个月等待这项服务工作.

我一直在挖掘文档,试图找到一种方法来抑制这些nil对象的传输.我知道我可以在每个POCO对象的每个单独属性上将EmitDefaultValue属性设置为false.除非我别无选择,否则我不打算为100多件物品做这件事.此外,我不相信我应该被迫使用DataContract属性注释我的类库对象.我也不想用DataContractSurrogates镜像我的类库.那只是淫秽.

当然,有一个配置选项,我可以指定序列化的默认行为EmitDefaultValue = false.我一直无法找到它.我希望其他人找到它,或者找到另一个全局选项来抑制XML中的null属性.

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

如果这不存在,那似乎是微软的巨大疏忽.

Leo*_*lev 3

我相信没有官方的方法可以在全球范围内设置此属性,也许是因为在大多数情况下它被描述为不推荐的做法

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

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; }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

using System.Runtime.Serialization;

namespace FooBar
{
    [DataContract]
    public class Foo
    {
        // Warning about type conflict.
        [DataMember]
        public string Bar { get; set; }
    }
}
Run Code Online (Sandbox Code Playgroud)

它将被DataContractSerializer序列化为:

<Foo xmlns="http://schemas.datacontract.org/2004/07/ConsoleApplication1"
     xmlns:i="http://www.w3.org/2001/XMLSchema-instance"/>
Run Code Online (Sandbox Code Playgroud)