创建正确序列化/反序列化派生类型的 XmlSerializer



我正在尝试创建一个 XmlSerializer,可以正确序列化和反序列化派生类型。请查看下面的代码。非常感谢使用 XmlAttributeOverrides 广告额外类型来创建适当的 XmlSerializer 并将 GetVehicleResponse 实例与 VehicleObject 序列化为"SUV"对象的任何帮助。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using InteractiveSoftworks.Framework.Xml;
using System.IO;
namespace DowncastTest
{
   [XmlType(Namespace="urn:Test/Service")]
   public class GetVehicleResponse
   {
      [XmlElement(IsNullable=true, Namespace="urn:Test")]
      public Vehicle VehicleObject;
   }
   [XmlType( Namespace = "urn:test" )]
   public class Vehicle
   {
      public string Model;
      public string Number { get; set; }
   }
   public class Car : Vehicle
   {
      public int Doors { get; set; }
   }
   public class SUV : Car
   {
      public int Engines { get; set; }
   }
   public class MotorCycle : Vehicle
   {
      public int Seats { get; set; }
   }
   public class SportsBike : MotorCycle
   {
      public int Mirrors { get; set; }
   }

   public class Program
   {
      static void Main( string[] args )
      {
         XmlAttributeOverrides overrides = new XmlAttributeOverrides();
         CreateAttributeOverrides( typeof( Car ), "urn:Test", overrides );
         CreateAttributeOverrides( typeof( SUV ), "urn:Test", overrides );
         CreateAttributeOverrides( typeof( MotorCycle ), "urn:Test", overrides );
         CreateAttributeOverrides( typeof( SportsBike ), "urn:Test", overrides );
         Type[] extraTypes = new Type[] { typeof( Car ), typeof( SUV ), typeof( MotorCycle ), typeof( SportsBike ) };
         XmlSerializer xs = new XmlSerializer( typeof( GetVehicleResponse ), overrides, extraTypes, new XmlRootAttribute() { ElementName = "GetVehicleResponse", Namespace = "urn:Test" }, "urn:Test" );
         MemoryStream ms = new MemoryStream();
         xs.Serialize( ms, new GetVehicleResponse() { VehicleObject = new SUV() { Number = "AP29", Model = "2011", Doors = 4, Engines = 2 } } );
         string s = Encoding.UTF8.GetString( ms.GetBuffer() );
         Console.WriteLine( s );
         Console.WriteLine( "Done..." );
         Console.ReadKey();
      }
      internal static void CreateAttributeOverrides( Type type, string projectNamespace, XmlAttributeOverrides overrides )
      {
         // redirect the type if no explicit XmlAttributeType namespace has been provided
         //
         XmlAttributes typeAttributes = new XmlAttributes( type );
         XmlTypeAttribute typeAttribute = null;
         if ( typeAttributes.XmlType != null ) // inherit existing methodType attributes if any
         {
            if ( string.IsNullOrEmpty(typeAttributes.XmlType.Namespace) ) // only set the namespace if it isn't already defined
            {
               typeAttribute = typeAttributes.XmlType;
               typeAttribute.Namespace = projectNamespace;
            }
         }
         else
         {
            string rootNamespace = string.Empty;
            // if type defined Xml Root Attributes then get the namespace and add to type attributes
            //
            if ( typeAttributes.XmlRoot != null )
               rootNamespace = typeAttributes.XmlRoot.Namespace;
            if ( string.IsNullOrEmpty( rootNamespace ) )
               rootNamespace = projectNamespace;
            typeAttribute = new XmlTypeAttribute() { Namespace = rootNamespace };
         }
         if ( typeAttribute != null )
            overrides.Add( type, new XmlAttributes() { XmlType = typeAttribute } );  // use a fresh XmlAttributes as we only want to globally override XmlTypeAttribute
      }
   }
}

我想你正在寻找 XmlIncludeAttribute

作为替代方法,可以使用 XmlSerializer 的一种形式,该形式支持可用于指定派生类型的额外类型参数: 从文档中:

还可以使用 extraTypes 参数指定派生自基类的类型。

根据我的经验,这很好用,但并非适用于所有情况,因为您需要准备好解决Microsoft实施中的潜在问题。有关详细信息,请参阅 XmlSerializer 文档中有关动态生成的程序集的部分。

最新更新