2017-02-21 46 views
3

我想反序列化XML到下面的類:如何讓XmlSerializer忽略某個類型的所有成員?

public partial class Delivery 
{ 
    public System.Nullable<System.DateTime> sentDate { get; set; } 
    public System.Nullable<System.DateTime> receivedDate { get; set; } 
    public System.Nullable<System.DateTime> responseDueDate { get; set; } 
} 

然而,在XML的日期是不是在一個XmlSerializer友好的格式。基於答案多張的問題,我加入這個類:

public partial class DateSafeDelivery : Delivery 
{ 
    [XmlElement("sentDate")] 
    public string sentDateString 
    { 
     internal get { return sentDate.HasValue ? XmlConvert.ToString(sentDate.Value) : null; } 
     set { sentDate = DateTime.Parse(value); } 
    } 
    [XmlElement("receivedDate")] 
    public string receivedDateString 
    { 
     internal get { return receivedDate.HasValue ? XmlConvert.ToString(receivedDate.Value) : null; } 
     set { receivedDate = DateTime.Parse(value); } 
    } 
    [XmlElement("responseDueDate")] 
    public string responseDueDateString 
    { 
     internal get { return responseDueDate.HasValue ? XmlConvert.ToString(responseDueDate.Value) : null; } 
     set { responseDueDate = DateTime.Parse(value); } 
    } 
} 

然後配置我重寫:

private static XmlAttributeOverrides GetOverrides() 
{ 
    var overrides = new XmlAttributeOverrides(); 
    var attributes = new XmlAttributes(); 
    attributes.XmlElements.Add(new XmlElementAttribute(typeof(DateSafeDelivery))); 
    overrides.Add(typeof(MyParent), "Delivery", attributes); 
    var ignore = new XmlAttributes { XmlIgnore = true }; 
    overrides.Add(typeof(DateTime?), ignore); 
    return overrides; 
} 

這將導致以下厚望:

Message=The string '2010-06-12T00:00:00 -05:00' is not a valid AllXsd value. 
Source=System.Xml.ReaderWriter 
StackTrace: 
    at System.Xml.Schema.XsdDateTime..ctor(String text, XsdDateTimeFlags kinds) 
    at System.Xml.XmlConvert.ToDateTime(String s, XmlDateTimeSerializationMode dateTimeOption) 
    at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderDeserializedAudit.Read1_NullableOfDateTime(Boolean checkType) 
    at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderDeserializedAudit.Read15_DateSafeDelivery(Boolean isNullable, Boolean checkType) 
    at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderDeserializedAudit.Read16_MyParent(Boolean isNullable, Boolean checkType) 

所以DateSafeDelivery是被使用,但日期的XmlIgnore正在被忽略。

它會工作,如果我轉:

overrides.Add(typeof(DateTime?), ignore); 

有:

new Dictionary<string, Type>() 
    { 
     { "sentDate", typeof(Delivery) }, 
     { "receivedDate", typeof(Delivery) }, 
     { "responseDueDate", typeof(Delivery) }, 
    } 
     .ToList() 
     .ForEach(t1 => overrides.Add(t1.Value, t1.Key, ignore)); 

而且,對於一類三次性很好。但是我有14個類共有三十個日期屬性。我知道我必須爲14個類添加覆蓋,但是有沒有辦法讓序列化程序忽略所有DateTime屬性?

我以爲XmlAttributeOverrides.Add Method (Type, XmlAttributes)會做到這一點。但它不起作用。爲什麼?這種方法是什麼?它有什麼作用?

回答

1

XmlAttributeOverrides.Add(Type, XmlAttributes)旨在將XML重寫屬性添加到類型本身,而不是返回所有返回該類型值的屬性。例如。如果你想要一個[XmlRoot("OverrideName")]屬性添加到DateSafeDelivery,你可以這樣做:

overrides.Add(typeof(DateSafeDelivery), 
    new XmlAttributes { XmlRoot = new XmlRootAttribute("OverrideName") }); 

沒有動態override屬性,忽略所有屬性返回給定類型,因爲沒有static XML serialization attribute能夠抑制所有屬性的序列化給定類型。以下甚至沒有編譯,因爲[XmlIgnore]只能應用於屬性或字段:

[XmlIgnore] public class IgnoreAllInstancesOfMe { } // Fails to compile. 

(至於爲什麼微軟沒有實施[XmlIgnore]應用於類型的支持 - 你需要問他們)

因此,你將需要引入類似下面的擴展方法:

public static partial class XmlAttributeOverridesExtensions 
{ 
    public static XmlAttributeOverrides IgnorePropertiesOfType(this XmlAttributeOverrides overrides, Type declaringType, Type propertyType) 
    { 
     return overrides.IgnorePropertiesOfType(declaringType, propertyType, new HashSet<Type>()); 
    } 

    public static XmlAttributeOverrides IgnorePropertiesOfType(this XmlAttributeOverrides overrides, Type declaringType, Type propertyType, HashSet<Type> completedTypes) 
    { 
     if (overrides == null || declaringType == null || propertyType == null || completedTypes == null) 
      throw new ArgumentNullException(); 
     XmlAttributes attributes = null; 
     for (; declaringType != null && declaringType != typeof(object); declaringType = declaringType.BaseType) 
     { 
      // Avoid duplicate overrides. 
      if (!completedTypes.Add(declaringType)) 
       break; 
      foreach (var property in declaringType.GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance)) 
      { 
       if (property.PropertyType == propertyType || Nullable.GetUnderlyingType(property.PropertyType) == propertyType) 
       { 
        attributes = attributes ?? new XmlAttributes { XmlIgnore = true }; 
        overrides.Add(declaringType, property.Name, attributes); 
       } 
      } 
     } 
     return overrides; 
    } 
} 

,做:

private static XmlAttributeOverrides GetOverrides() 
    { 
     var overrides = new XmlAttributeOverrides(); 

     var attributes = new XmlAttributes(); 
     attributes.XmlElements.Add(new XmlElementAttribute(typeof(DateSafeDelivery))); 
     overrides.Add(typeof(MyParent), "Delivery", attributes); 

     // Ignore all DateTime properties in DateSafeDelivery 
     var completed = new HashSet<Type>(); 
     overrides.IgnorePropertiesOfType(typeof(DateSafeDelivery), typeof(DateTime), completed); 
     // Add the other 14 types as required 

     return overrides; 
    } 

也請注意,DateSafeDeliveryDateString屬性必須有公共 get和set方法,例如:

public partial class DateSafeDelivery : Delivery 
{ 
    [XmlElement("sentDate")] 
    public string sentDateString 
    { 
     get { return sentDate.HasValue ? XmlConvert.ToString(sentDate.Value, XmlDateTimeSerializationMode.Utc) : null; } 
     set { sentDate = DateTime.Parse(value); } 
    } 

XmlSerializer不能序列化的屬性,是不是完全公開。

順便說一下,請注意,您必須靜態緩存任何使用覆蓋構造的XmlSerializer,以避免嚴重的內存泄漏,如this answer中所述。

+1

因此,XmlAttributeOverrides.Add(Type,XmlAttributes)僅適用於被反序列化的類型。得到它了。 最後,我列出了代碼中的每個屬性。我考慮過反思,但不希望計算機每次都能弄清楚我花了3分鐘才能說出來。 此外,我看到內存泄漏的答案,並靜態使用XmlSerializer。 而內部獲取正在爲反序列化工作。這是我關心這門課程的唯一方向。 謝謝。 –

相關問題