C# 将 Nullable<DateTime> 序列化为 XML

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2074240/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 23:16:45  来源:igfitidea点击:

Serializing a Nullable<DateTime> in to XML

c#xml-serializationnullable

提问by Scott Chamberlain

I am trying to serialize a class several of the data-members are Nullable objects, here is a example

我正在尝试序列化一个类,其中几个数据成员是 Nullable 对象,这是一个示例

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

However at runtime I get the error

但是在运行时我收到错误

Cannot serialize member 'AccountExpirationDate' of type System.Nullable`1[System.DateTime]. XmlAttribute/XmlText cannot be used to encode complex types.

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

However I checked and Nullable is a SerializableAttribute. What am I doing wrong?

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

采纳答案by David M

You can only serialize it as an XmlElement, not as an XmlAttribute, as the representation is too complex for an attribute. That's what the exception is telling you.

您只能将其序列化为XmlElement,而不是XmlAttribute,因为表示对于属性来说太复杂了。这就是例外告诉你的。

回答by Marc Gravell

If you just want it to work, then perhaps:

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

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);
    }
}

This will only include the attribute when there is a non-null value.

这将仅在存在非空值时包括该属性。

回答by fre0n

I've used something like this many times.

我已经多次使用这样的东西。

[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;
    }
}

回答by Rodrigo Perez Burgues

Define a Serializable that encapsulates your funcionality.

定义一个 Serializable 来封装您的功能。

Here's are and example.

这是示例。

[XmlAttribute("AccountExpirationDate")]  
public SerDateTime AccountExpirationDate   
{   
  get { return _SerDateTime ; }   
  set { _SerDateTime = value; }   
}  


/// <summary>
/// Serialize DateTime Class (<i>yyyy-mm-dd</i>)
/// </summary>
public class SerDateTime : IXmlSerializable {
    /// <summary>
    /// Default Constructor when time is not avalaible
    /// </summary>
    public SerDateTime() { }
    /// <summary>
    /// Default Constructor when time is avalaible
    /// </summary>
    /// <param name="pDateTime"></param>
    public SerDateTime(DateTime pDateTime) {
        DateTimeValue = pDateTime;
    }

    private DateTime? _DateTimeValue;
    /// <summary>
    /// Value
    /// </summary>
    public DateTime? DateTimeValue {
        get { return _DateTimeValue; }
        set { _DateTimeValue = value; }
    }

    // Xml Serialization Infrastructure
    void IXmlSerializable.WriteXml(XmlWriter writer) {
        if (DateTimeValue == null) {
            writer.WriteString(String.Empty);
        } else {
            writer.WriteString(DateTimeValue.Value.ToString("yyyy-MM-dd"));
            //writer.WriteString(SerializeObject.SerializeInternal(DateTimeValue.Value));
        }
    }

    void IXmlSerializable.ReadXml(XmlReader reader) {
        reader.ReadStartElement();
        String ltValue = reader.ReadString();
        reader.ReadEndElement();
        if (ltValue.Length == 0) {
            DateTimeValue = null;
        } else {                
            //Solo se admite yyyyMMdd
            //DateTimeValue = (DateTime)SerializeObject.Deserialize(typeof(DateTime), ltValue);
            DateTimeValue = new DateTime(Int32.Parse(ltValue.Substring(0, 4)),
                                Int32.Parse(ltValue.Substring(5, 2)),
                                Int32.Parse(ltValue.Substring(8, 2)));                                    
        }
    }

    XmlSchema IXmlSerializable.GetSchema() {
        return (null);
    }
}
#endregion

回答by Pankaj Pawar

I was stuck into the similar problem. I had a datetime property (as XmlAttribute) in a class which was exposed in the WCF service.

我陷入了类似的问题。我在 WCF 服务中公开的类中有一个日期时间属性(作为 XmlAttribute)。

Below is what I faced and the solution that worked for me : 1) XmlSerializer class was not serialising XmlAttribute of nullable type

以下是我面临的问题以及对我有用的解决方案:1) XmlSerializer 类没有序列化可为空类型的 XmlAttribute

[XmlAttribute]
public DateTime? lastUpdatedDate { get; set; }
Exception thrown : Cannot serialize member 'XXX' of type System.Nullable`1. 

2) Some posts suggest to replace [XmlAttribute] with [XmlElement(IsNullable =true)]. But this will serialize the Attribute as an Element which is totally useless. However it works fine for XmlElements

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

3) Some suggest to implement IXmlSerializable interface into your class, but that doesn't allow WCF service to be called from WCF consuming application. So this too does not work in this case.

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

Solution :

解决方案 :

Don't mark property as nullable, instead use a ShouldSerializeXXX() method to put your constraint.

不要将属性标记为可为空,而是使用 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
}