我正在尝试创建一个 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 文档中有关动态生成的程序集的部分。