使用XmlSerializer序列化多种类型的数组我正在尝试使用XMLSerializer生成如下所示的XML,其中内容是一个数组,但是元素可以不同类型(在本例中为,和)。是否可以?...Unit-A-1212thisisthename8FOOBAR8XML121XMLCustomer111SanJoseKevin123456789....假设数组中所有可能的类型在编译时都是已知的,您可以为每个已知类型创建一个数组应用多个[XmlArrayItem(String,Type)]属性。Type参数是可以出现在数组中的特定派生类型,String参数是要与该类型关联的元素名称。[XmlArray(String)]属性应用于整个数组属性以指定数组的名称并在两个级别而不是一个级别对其进行序列化。例如:publicclassDocument{[XmlArray("create")][XmlArrayItem("vendor",typeof(Vendor))][XmlArrayItem("customer",typeof(Customer))][XmlArrayItem("asset",typeof(资产))]publicCreateBase[]创建{get;放;}}其中publicabstractclassCreateBase{}publicclassVendor:CreateBase{publicstringvendorid{get;放;}公共字符串名称{get;放;}publicstringvcf_bill_siteid3{}}publicclassCustomer:CreateBase{publicstringCUSTOMERID{get;放;}公共字符串名称{得到;放;}}publicclassAsset:CreateBase{publicstringcreatedAt{get;放;}publicstringcreatedBy{get;放;}publicstringserial_number{得到;放;(使用抽象基类型只是我的偏好。您可以使用对象作为基类型:publicobject[]Create{get;set;})更新XmlSerializer很难序列化,因为它通过动态代码生成工作。也就是说,当您第一次创建XmlSerializer时,它使用反射编写c#代码来序列化和反序列化所有静态可发现的引用类型,然后编译并将该代码加载到动态DLL中以执行实际工作。没有为无法静态发现的类型创建代码,因此(反)序列化将失败。有两种方法可以解决此限制:在运行时查找列表中的所有派生类型,然后构造XmlAttributeOverrides,为多态数组属性添加XmlAttributes,然后用找到的子类型填充数组属性的XmlArrayItems。然后将XmlAttributeOverrides传递给适当的XmlSerializer构造函数。注意-您必须在适当的哈希表中缓存和重用XmlSerializer,否则会发生巨大的资源泄漏。看这里。有关如何执行此操作的示例,请参见此处:ForcingXMLserializationofXmlDefaultValuevalues。在运行时查找列表中的所有派生类型,并将它们存储在实现IXmlSerializable的自定义列表子类中。由于必须缓存XmlSerializer的麻烦,我倾向于第二种方法。要发现所有派生类型:publicstaticclassTypeExtensions{publicstaticIEnumerableDerivedTypes(thisIEnumerablebaseTypes){varassemblys=baseTypes.SelectMany(t=>t.Assembly.GetReferencingAssembliesAndSelf()).Distinct();返回程序集.SelectMany(a=>a.GetTypes()).Where(t=>baseTypes.Any(baseType=>baseType.IsAssignableFrom(t))).Distinct();}}publicstaticclassAssemblyExtensions{publicstaticIEnumerableGetAllAssemblies(){//改编自//https://stackoverflow.com/questions/851248/c-sharp-reflection-get-all-active-assemblies-in-a-解决方案returnAssembly.GetEntryAssembly().GetAllReferencedAssemblies();}publicstaticIEnumerableGetAllReferencedAssemblies(thisAssemblyroot){//警告:Assembly.GetAllReferencedAssemblies()将优化掉任何引用,如果//没有明确使用来自引用程序集的那个程序集中的类型--//并且简单添加像[XmlInclude(typeof(T))]这样的属性似乎不会o//诀窍。请参阅//https://social.msdn.microsoft.com/Forums/vstudio/en-US/17f89058-5780-48c5-a43a-dbb4edab43ed/getreferencedassemblies-not-returning-complete-list?forum=netfxbcl//因此如果例如,您正在使用它来发现基类型的所有派生类型,派生类型的程序集//必须至少包含一种直接或间接地从根程序集显式引用的类型。varlist=newHashSet();varstack=newStack();堆栈.推(根);做{varasm=stack.Pop();收益回报汇编;foreach(asm.GetReferencedAssemblies()中的var引用)if(!list.Contains(reference.FullName)){stack.Push(Assembly.Load(reference));list.Add(reference.FullName);}}while(stack.Count>0);}publicstaticIEnumerableGetReferencingAssemblies(thisAssemblytarget){if(target==null)thrownewArgumentNullException();//程序集可以有循环引用://http://stackoverflow.com/questions/1316518/how-did-micros经常创建具有循环引用的程序集//所以天真的算法是行不通的。vardone=newHashSet();varroot=Assembly.GetEntryAssembly();varallAssemblies=root.GetAllReferencedAssemblies().ToList();foreach(GetAllAssemblies()中的varassembly){if(target==assembly)continue;如果(完成。包含(程序集))继续;varrefersTo=(assembly==root?allAssemblies:assembly.GetAllReferencedAssemblies()).Contains(target);完成。添加(程序集);if(refersTo)yieldreturnassembly;}}publicstaticIEnumerableGetReferencingAssembliesAndSelf(thisAssemblytarget){returnnew[]{target}.Concat(target.GetReferencingAssemblies());}}然后,发现自己的类型的多状态表:T)==typeof(object)){thrownewInvalidOperationException("无法创建XmlPolymorphicList");}}内部密封类DerivedTypeDictionary{DictionaryderivedTypeNames;DictionaryderivedTypes;DerivedTypeDictionary(){derivedTypeNames=typeof(T).DerivedTypes().ToDictionary(t=>t,t=>t.DefaultXmlElementName());derivedTypes=derivedTypeNames.ToDictionary(p=>p.Value,p=>p.Key);//如果名称不唯一将抛出异常}publicstaticDerivedTypeDictionaryInstance{get{returnSingleton.Instance;}}publicstringGetName(Typetype){returnderivedTypeNames[type];}publicTypeGetType(stringname){returnderivedTypes[name];}}publicXmlPolymorphicList():base(){}publicXmlPolymorphicList(IEnumerableitems):base(items){}#区域IXmlSerializable成员XmlSchemaIXmlSerializable.GetSchema(){returnnull;}voidIXmlSerializable.ReadXml(XmlReaderreader){reader.ReadStartElement();while(reader.NodeType==XmlNodeType.Element){varname=reader.Name;vartype=DerivedTypeDictionary.实例。获取类型(名称);varitem=(T)(newXmlSerializer(type).Deserialize(reader));如果(项目!=null)添加(项目);}}voidIXmlSerializable.WriteXml(XmlWriterwriter){foreach(variteminthis){newXmlSerializer(item.GetType()).Serialize(writer,item);}}#endregion}publicstaticclassXmlSerializationHelper{publicstaticstringDefaultXmlElementName(thisTypetype){varxmlType=type.GetCustomAttribute();如果(xmlType!=null&&!string.IsNullOrEmpty(xmlType.TypeName))返回xmlType.TypeName;返回类型.名称??;}}publicclassSingletonwhereT:class{//显式静态构造函数告诉C#编译器//不要将类型标记为beforefieldinitstaticSingleton(){}//////充当单例类实例化器的私有嵌套类。这个类不应该在外面访问"/>///classNested{//////显式静态构造函数告诉C#编译器不要将类型标记为beforefieldinit///staticNested(){}//////静入姿态变量///internalstaticreadonlyTinstance=(T)Activator.CreateInstance(typeof(T),true);}publicstaticTInstance{get{returnNested.instance;在c#类中,只需确保始终返回可能返回的任何可能类型的空数组:[Serializable]publicclasscreate{publiccreate(){vendor=newVendor[0];客户=新客户[0];资产=新资产[0];}}客户[]客户{得到;放;}资产[]资产{得到;放;}}[Serializable]publicclassVendor{publicstringvendorid{get;放;}publicstringname}publicstringvcf_bill_siteid3{get;放;}}[可序列化]publicclassCustomer{publicstringCUSTOMERID{get;放;}公共字符串名称{得到;放;}}[Serializable]publicclassAsset{publicstringcreatedAt{get;放;}publicstringcreatedBy{get;放;}publicstringserial_number{得到;以上就是C#学习教程:使用XmlSerializer序列化多种类型数组的全部内容分享。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
