2017-02-21 49 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。 而内部获取正在为反序列化工作。这是我关心这门课程的唯一方向。 谢谢。 –

相关问题