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

时间:2011-05-09 18:21:24

标签: c# xml xmlserializer derived-types

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

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
      }

   }
}

2 个答案:

答案 0 :(得分:0)

我认为您正在寻找XmlIncludeAttribute

答案 1 :(得分:0)

作为替代方法,您可以使用a form of the XmlSerializer that supports an extra types parameter that you can use to specify derived types: 来自doc:

  

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

这在我的经验中运作良好,但并不适用于所有情况,因为您需要准备好解决Microsoft实施中的潜在问题。有关详细信息,请参阅XmlSerializer doc中有关动态生成的装配的部分。