C# 如何反序列化没有null值的复杂XML元素? 一些价值 一些价值

C# 如何反序列化没有null值的复杂XML元素? 一些价值 一些价值,c#,xml,serialization,C#,Xml,Serialization,我有上面的xml,Address元素是一个复杂的对象。当我试图反序列化到C#object时,address对象中的所有属性都设置为null,但我的要求是将address对象本身设置为null。有没有办法做到这一点?您可以使用XmlIgnore属性排除对象的属性 <Customer> <FirstName>SomeValue</FirstName> <LastName>Somevalue</LastName> <Address/&g

我有上面的xml,Address元素是一个复杂的对象。当我试图反序列化到C#object时,address对象中的所有属性都设置为null,但我的要求是将address对象本身设置为null。有没有办法做到这一点?

您可以使用XmlIgnore属性排除对象的属性

<Customer>
<FirstName>SomeValue</FirstName>
<LastName>Somevalue</LastName>
<Address/>
</Customer>

为了确认您的问题,您会问:在反序列化XML时,我是否可以将空元素映射到
null
属性值,而将非空元素映射到非
null
属性值?

假设您正在使用,这不是开箱即用的实现<当属性(通常缩写为
xsi:nil
)具有值
“true”
时,code>XmlSerializer仅将元素映射到
null
值。发件人:

XmlSerializer类将nil属性的真值与空引用相等,执行以下运行时转换:

  • 将XML文档反序列化为对象时:如果XmlSerializer类遇到指定xsi:nil=“true”的XML元素,它将为相应的对象分配一个空引用(如果适用)
  • 将对象序列化到XML文档中时:如果XmlSerializer类遇到对应于XML元素的对象的空引用,它会生成指定xsi:nil=“true”的元素,或者完全忽略该元素,具体取决于是否应用nillable=“true”设置
由于
xsi:nil
不存在于空的
元素中,因此它不会自动映射到
null

作为一种解决方法,您可以将
地址
的额外“代理”属性引入
客户
中,在反序列化过程中,该属性检查要设置的
地址
是否具有默认值,如果是,则将基础地址值设置为
null
。例如,如果您的类看起来像:

[XmlIgnore] 
public Address {get; set;}
您可以通过以下两种方式完成此操作:

  • 带着沉思。介绍以下扩展方法:

    public class Address
    {
        public string Street1 { get; set; }
        public string Street2 { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string Zip { get; set; }
        public string Country { get; set; }
    }
    
    public class Customer
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public Address Address { get; set; }
    }
    
    属性
    SerializableAddress
    使用反射检查传入的
    地址是否有任何非默认值。如果不是,则基础属性设置为null

    这个解决方案是健壮的和可重用的,但是由于它使用反射,所以性能可能不是很好

  • 使用标准接口检查给定类型中是否设置了任何属性。首先,介绍以下内容:

    public class Customer
    {
        public string FirstName { get; set; }
    
        public string LastName { get; set; }
    
        [XmlIgnore]
        public Address Address { get; set; }
    
        [XmlElement("Address")]
        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
        public Address SerializableAddress
        {
            get
            {
                return Address;
            }
            set
            {
                if (value != null && value.MembersAreDefault())
                    value = null;
                Address = value;
            }
        }
    }
    
    接下来,为
    地址实现该接口:

    public interface IHasDefaultMemberValues
    {
        bool MembersAreDefault();
    }
    
    最后,按照与解决方案1相同的方式修改
    客户

    此解决方案是有效的,但取决于在将新属性添加到
    客户时正确维护
    成员redefault()


  • 您能否为您的
    客户
    地址
    类共享c?请包括一个。谢谢DBC。但在反序列化字符串之前,我使用正则表达式从字符串中删除空节点,它对我有效。
    public interface IHasDefaultMemberValues
    {
        bool MembersAreDefault();
    }
    
    public class Address : IHasDefaultMemberValues
    {
        // Properties as above.
    
        #region IHasDefaultMemberValues Members
    
        public virtual bool MembersAreDefault()
        {
            return Street1 == null && Street2 == null && City == null && State == null && Zip == null && Country == null;
        }
    
        #endregion
    }