如何解决:“您需要将XmlChoiceIdentifierAttribute添加到成员中”

我正在尝试使用来更改将我的类序列化为 XML 的方式。我需要排除某些属性,并按特定顺序包含其他属性。XmlAttributeOverrides


我在这里有这个代码:


// XML Attribute Overrrides

public static XmlAttributeOverrides GetXMLAttributeOverrides(Type theType, List<string> propertiesToInlcudeInOrder, List<string> allColumnNames)

{

    try

    {

        if (propertiesToInlcudeInOrder != null)

        {

            XmlAttributeOverrides theXMLAttributeOverrides = new XmlAttributeOverrides();

            if (propertiesToInlcudeInOrder.Count > 0)

            {

                XmlAttributes mainNewXMLAttributes = new XmlAttributes();

                mainNewXMLAttributes.XmlIgnore = false;


                XmlAttributes ignoreXMLAttributes = new XmlAttributes();

                ignoreXMLAttributes.XmlIgnore = true;


                List<string> propertiesToNotInclude = new List<string>();

                foreach (string theColumnName in allColumnNames)

                {

                    string thePropertyName = theColumnName;

                    bool addProperty = true;

                    foreach (string propertyToInclude in propertiesToInlcudeInOrder)

                    {

                        if (thePropertyName == propertyToInclude)

                        {

                            addProperty = false;

                            break;

                        }

                    }


                    if (addProperty)

                    {

                        propertiesToNotInclude.Add(thePropertyName);

                    }

                }


元芳怎么了
浏览 183回答 1
1回答

胡说叔叔

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