Creating XmlSerializer that serializes/deserializes derived types correctly

浪尽此生 提交于 2019-12-11 10:49:24

问题


I'm trying to create an XmlSerializer that serialize and deserializes derived types properly. Please take a look at the code below. Any assistance in using XmlAttributeOverrides ad extra types to create proper XmlSerializer and serialize an instance of GetVehicleResponse with VehicleObject as "SUV" object is greatly appreciated.

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
      }

   }
}

回答1:


I think you are looking for the XmlIncludeAttribute




回答2:


As an alternative approach, you can use a form of the XmlSerializer that supports an extra types parameter that you can use to specify derived types: From the doc:

You can also use the extraTypes parameter to specify types derived from a base class.

This works fine in my experience, but is not perfect for every situation since you need to be prepared to address potential issues in Microsoft's implementation. See the section on Dynamically Generated Assemblies in the XmlSerializer doc for details.



来源:https://stackoverflow.com/questions/5940835/creating-xmlserializer-that-serializes-deserializes-derived-types-correctly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!