将Nullable <DateTime>序列化为XML

Sco*_*ain 34 c# nullable xml-serialization

我试图序列化一个类的几个数据成员是Nullable对象,这里是一个例子

[XmlAttribute("AccountExpirationDate")]
public Nullable<DateTime> AccountExpirationDate 
{ 
  get { return userPrincipal.AccountExpirationDate; } 
  set { userPrincipal.AccountExpirationDate = value; } 
}
Run Code Online (Sandbox Code Playgroud)

但是在运行时我得到了错误

无法序列化System.Nullable`1 [System.DateTime]类型的成员'AccountExpirationDate'.XmlAttribute/XmlText不能用于编码复杂类型.

但是我检查过Nullable是一个SerializableAttribute.我究竟做错了什么?

Mar*_*ell 43

如果你只是想让它起作用,那么也许:

using System;
using System.ComponentModel;
using System.Xml.Serialization;
public class Account
{
    // your main property; TODO: your version
    [XmlIgnore]
    public Nullable<DateTime> AccountExpirationDate {get;set;}

    // this is a shim property that we use to provide the serialization
    [XmlAttribute("AccountExpirationDate")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    public DateTime AccountExpirationDateSerialized
    {
        get {return AccountExpirationDate.Value;}
        set {AccountExpirationDate = value;}
    }

    // and here we turn serialization of the value on/off per the value
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
    public bool ShouldSerializeAccountExpirationDateSerialized()
    {
        return AccountExpirationDate.HasValue;
    }

    // test it...
    static void Main()
    {
        var ser = new XmlSerializer(typeof(Account));
        var obj1 = new Account { AccountExpirationDate = DateTime.Today };
        ser.Serialize(Console.Out, obj1);
        Console.WriteLine();
        var obj2 = new Account { AccountExpirationDate = null};
        ser.Serialize(Console.Out, obj2);
    }
}
Run Code Online (Sandbox Code Playgroud)

这将仅包含非空值时的属性.

  • @Scott是的,ShouldSerialize*是框架的多个部分和多个序列化库使用的模式 (3认同)

Dav*_*d M 28

您只能将其序列化为XmlElement,而不是因为XmlAttribute表示对于属性而言过于复杂.这就是异常告诉你的.

  • 多个类似问题均参考该问题的答案。然而,还没有答案给我任何线索来解释“为什么”XmAttribute 在“null”时不能简单地“不序列化”(使用 ShouldSerializexxx 范例)。没有理由它不工作,因此 Marc 下面的答案是它的详细版本。如果我们可以输入它,序列化库也可以做到吗?有什么线索吗? (2认同)

fre*_*e0n 17

我曾多次使用过这样的东西.

[XmlIgnore]
public Nullable<DateTime> AccountExpirationDate 
{ 
    get { return userPrincipal.AccountExpirationDate; } 
    set { userPrincipal.AccountExpirationDate = value; } 
}

///
/// <summary>Used for Xml Serialization</summary>
///
[XmlAttribute("AccountExpirationDate")]
public string AccountExpirationDateString
{
    get
    {
        return AccountExpirationDate.HasValue
            ? AccountExpirationDate.Value.ToString("yyyy/MM/dd HH:mm:ss.fff")
            : string.Empty;
    }
    set
    {
        AccountExpirationDate =
            !string.IsNullOrEmpty(value)
            ? DateTime.ParseExact(value, "yyyy/MM/dd HH:mm:ss.fff")
            : null;
    }
}
Run Code Online (Sandbox Code Playgroud)


Pan*_*war 5

我陷入了类似的问题。我在WCF服务中公开的类中有一个datetime属性(如XmlAttribute)。

以下是我所面对的以及对我有用的解决方案:1)XmlSerializer类未序列化可空类型的XmlAttribute

[XmlAttribute]
public DateTime? lastUpdatedDate { get; set; }
Exception thrown : Cannot serialize member 'XXX' of type System.Nullable`1. 
Run Code Online (Sandbox Code Playgroud)

2)一些帖子建议将[XmlAttribute]替换为[XmlElement(IsNullable = true)]。但这会将属性序列化为元素,这是完全没有用的。但是,它对于XmlElements正常工作

3)有些人建议在您的类中实现IXmlSerializable接口,但这不允许从使用WCF的应用程序中调用WCF服务。因此,这在这种情况下也不起作用。

解决方案:

不要将属性标记为可为空,而应使用ShouldSerializeXXX()方法放置约束。

[XmlAttribute]
public DateTime lastUpdatedDate { get; set; }
public bool ShouldSerializelastUpdatedDate ()
{
   return this.lastUpdatedDate != DateTime.MinValue; 
   // This prevents serializing the field when it has value 1/1/0001       12:00:00 AM
}
Run Code Online (Sandbox Code Playgroud)

  • 我不主张。如果不准确,至少在上下文中。我的目的是为面临类似问题的人提供一个提示。 (3认同)
  • “不要将属性标记为可为空”。所以这并不能回答这个问题,因为需要可空性。 (2认同)