1 回答
TA贡献1804条经验 获得超8个赞
您的基本问题是,您正在为每个属性添加多个覆盖 [XmlElement] 属性,因为您正在对所有属性使用单个实例,这会累积为所有属性定义的对象。mainNewXMLAttributesXmlElementAttribute
要解决此问题,您需要为循环中的每个属性分配一个 fresh,如以下更正和简化的版本所示:mainNewXMLAttributesforeach (var propertyNameToIncludeInOrder in propertiesToInlcudeInOrder)GetXMLAttributeOverrides()
public static partial class ReportingManipulation
{
public static XmlAttributeOverrides GetXMLAttributeOverrides(Type theType, IList<string> propertiesToInlcudeInOrder)
{
var allProperties = theType.GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance).Select(p => p.Name);
return GetXMLAttributeOverrides(theType, propertiesToInlcudeInOrder, allProperties);
}
// XML Attribute Overrrides
public static XmlAttributeOverrides GetXMLAttributeOverrides(Type theType, IList<string> propertiesToInlcudeInOrder, IEnumerable<string> allProperties)
{
if (propertiesToInlcudeInOrder == null || propertiesToInlcudeInOrder.Count == 0)
return null;
var theXMLAttributeOverrides = new XmlAttributeOverrides();
// To Add In Order
int counter = 1;
foreach (var propertyNameToIncludeInOrder in propertiesToInlcudeInOrder)
{
// Allocate a fresh instance of XmlAttributes for each property, because we are defining a different
// XmlElementAttribute for each
var mainNewXMLAttributes = new XmlAttributes { XmlIgnore = false };
// Specify the element order XmlElementAttribute and attach to the XmlAttributes
var theXMLElementAttributeToAdd = new XmlElementAttribute { Order = counter };
mainNewXMLAttributes.XmlElements.Add(theXMLElementAttributeToAdd);
// Attach the override XmlElementAttribute to the property propertyNameToIncludeInOrder
theXMLAttributeOverrides.Add(theType, propertyNameToIncludeInOrder, mainNewXMLAttributes);
counter++;
}
// To Ignore
// Using System.Linq.Enumerable.Except()
var propertiesToNotInclude = allProperties.Except(propertiesToInlcudeInOrder);
var ignoreXMLAttributes = new XmlAttributes { XmlIgnore = true };
foreach (var propertyNameToNotInlcude in propertiesToNotInclude)
{
// Attach the override XmlElementAttribute to the property propertyNameToIncludeInOrder
// No need to allocate a fresh instance of ignoreXMLAttributes for each, because the instances would all be identical
theXMLAttributeOverrides.Add(theType, propertyNameToNotInlcude, ignoreXMLAttributes);
}
return theXMLAttributeOverrides;
}
}
为什么你的代码不起作用?在初始代码中,您需要执行以下操作:
XmlAttributes mainNewXMLAttributes = new XmlAttributes();
mainNewXMLAttributes.XmlIgnore = false;
int counter = 1;
foreach (string propertyNameToIncludeInOrder in propertiesToInlcudeInOrder)
{
XmlElementAttribute theXMLElementAttributeToAdd = new XmlElementAttribute(propertyNameToIncludeInOrder);
theXMLElementAttributeToAdd.ElementName = propertyNameToIncludeInOrder;
theXMLElementAttributeToAdd.Order = counter;
mainNewXMLAttributes.XmlElements.Add(theXMLElementAttributeToAdd);
theXMLAttributeOverrides.Add(theType, propertyNameToIncludeInOrder, mainNewXMLAttributes);
counter++;
}
现在,方法 XmlAttributeOverrides.Add(Type, String, XmlAttributes) 被记录为按如下方式工作:
将对象添加到对象集合中。该参数指定要重写的对象。该参数指定被覆盖的成员的名称。XmlAttributesXmlAttributestypemember
因此,当最终构造 时,的内容将应用于命名参数。当您为所有参数仅构造 实例时,其数组将包含与所有参数对应的元素名称!即,您的代码尝试将多个属性应用于每个命名参数,仅在覆盖名称和顺序上有所不同。这说明了您需要将 XmlChoiceIdentifierAttribute 添加到 'TextColumn' 成员的异常 -- 如果属性值是多态的,并且您希望将不同的元素名称分配给不同的值类型,则只能将多个元素名称附加到属性。mainNewXMLAttributesXmlSerializermainNewXMLAttributesXmlElements[XmlElement]
笔记
生成 with 覆盖时,必须静态缓存它,并在以后重用它以避免严重的内存泄漏,如使用 StreamReader 和 XmlSerializer 的内存泄漏中所述。XmlSerializer
我不建议无条件地吞下异常,并在低级实用工具方法或对象构造函数中将它们作为错误消息呈现给用户。
在这里演示工作小提琴。
- 1 回答
- 0 关注
- 182 浏览
添加回答
举报
