[英]How to deserialize child object into list of parent (ex, List<Parent>) based on values of xml nodes?
我有一个名为 VehicleInfo 的 XML 文件。 我想在车辆列表中反序列化 VehicleInfo。 现在我有一个名为 Vehicle 的基类和三个名为 Car、Bike、Truck 的派生类。 如何根据xml中Vehicle节点的值反序列化车辆的特定对象。 (例如,如果节点值为 Car,则汽车的对象应存储在车辆列表中)
<Vehicles>
<Vehicle>Car</Vehicle>
<Vehicle>Bike</Vehicle>
<Vehicle>Truck</Vehicle>
</Vehicles>
例如,
车辆列表类:
public class VehicleList
{
List<Vehicle> lstVehicles = new List<Vehicle>();
}
车辆类别:
public class Vehicle
{
public string name = "Vehicle";
}
汽车类:
public class Car : Vehicle
{
public Car()
{
name = "Car";
}
}
自行车类:
public class Bike : Vehicle
{
public Bike()
{
name = "Bike";
}
}
卡车类别:
public class Truck : Vehicle
{
public Truck()
{
name = "Truck";
}
}
这个 Vehicle 程序只是一个例子,
那么,如何根据节点 Vehicle 的值反序列化 VehicleList 类中的车辆列表中的特定对象(例如汽车、自行车或卡车)。
这是要序列化的代码和结果。 XML 不能将数组作为根元素。 所以在这种情况下,有两个类是有意义的:Vehicles 和 Vehicle。 见下面的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication107
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
Vehicles vehicles = new Vehicles()
{
vehicles = new List<Vehicle>() {
new Car() { make = "BMW"},
new Bike() { make = "Buffalo"},
new Truck() { make = "MAC"}
}
};
XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;
XmlWriter writer = XmlWriter.Create(FILENAME, settings);
XmlSerializer serializer = new XmlSerializer(typeof(Vehicles));
serializer.Serialize(writer, vehicles);
}
}
public class Vehicles
{
[XmlElement("Vehicle")]
public List<Vehicle> vehicles { get; set; }
}
[XmlInclude(typeof(Car))]
[XmlInclude(typeof(Bike))]
[XmlInclude(typeof(Truck))]
public class Vehicle
{
public string make { get; set; }
}
public class Car : Vehicle
{
}
public class Bike : Vehicle
{
}
public class Truck : Vehicle
{
}
}
这是结果:
<?xml version="1.0" encoding="utf-8"?>
<Vehicles xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Vehicle xsi:type="Car">
<make>BMW</make>
</Vehicle>
<Vehicle xsi:type="Bike">
<make>Buffalo</make>
</Vehicle>
<Vehicle xsi:type="Truck">
<make>MAC</make>
</Vehicle>
</Vehicles>
XmlSerializer
支持某些类型的继承建模,但是:它基于元素/属性,而不是实际值; 我不知道有任何 API 可以支持您想要的数据,因此您必须将它们反序列化为字符串,然后将它们后处理为您想要的。
这将是可能的事情的一个例子是:
<Vehicles>
<Car>...car things...</Car>
<Bike>...bike things...</Bike>
<Truck>...truck things...</Truck>
</Vehicles>
这可以通过以下方式实现:
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
[XmlInclude(typeof(Car))] // technically you only need XmlInclude
[XmlInclude(typeof(Bike))] // if you're using xsi:type resolution
[XmlInclude(typeof(Truck))] // but... it doesn't hurt us here
public abstract class Vehicle { }
public class Car : Vehicle { }
public class Truck : Vehicle { }
public class Bike : Vehicle { }
[XmlRoot("Vehicles")]
public class MyRoot
{
[XmlElement("Car", Type = typeof(Car))]
[XmlElement("Truck", Type = typeof(Truck))]
[XmlElement("Bike", Type = typeof(Bike))]
public List<Vehicle> Items { get; } = new List<Vehicle>();
}
static class P
{
static void Main()
{
var root = new MyRoot
{
Items =
{
new Car(),
new Bike(),
new Truck(),
}
};
var ser = new XmlSerializer(typeof(MyRoot));
var ns = new XmlSerializerNamespaces();
ns.Add("", "");
ser.Serialize(Console.Out, root, ns);
}
}
好吧,这会很长……
您可以使用此解决方案.net-fiddle-here
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml.Serialization;
public class Program
{
public static void Main()
{
var root = new Vehicles
{
Items =
{
new Vehicle() { Name = "Car"},
new Vehicle() { Name = "Truck"},
new Vehicle() { Name = "Bike"}
}
};
var xmlSerializer = new XmlSerializer(typeof(Vehicles));
var memoryStream = new MemoryStream();
TextWriter stringWriter = new StreamWriter(memoryStream, System.Text.Encoding.UTF8);
xmlSerializer.Serialize(stringWriter, root);
string xml = System.Text.Encoding.UTF8.GetString(memoryStream.ToArray());
//Make XML
var obj = root;
var xmlString = obj.XmlSerializeToString();
//Make Object with Direct Deserialization
var vehicles = xmlString.XmlDeserializeFromString<Vehicles>();
//Make polymorphic object from generic vehicles with some "logic"
var polymorphicVehicles = new List<Vehicle>(); // ****** THIS is the collection you requested!!!! *********
// itterate all vehicles
foreach (var item in vehicles.Items)
{
// use json serialization, because casting Parent to Child is not acceptable
var jsonVehicle = JsonConvert.SerializeObject(item);
// depending on the Name of the vehicle, create a corresponding object
switch (item.Name)
{
case "Car":
var aCar = JsonConvert.DeserializeObject<Car>(jsonVehicle);
polymorphicVehicles.Add(aCar);
break;
case "Truck":
var aTruck = JsonConvert.DeserializeObject<Truck>(jsonVehicle);
polymorphicVehicles.Add(aTruck);
break;
case "Bike":
var aBike = JsonConvert.DeserializeObject<Bike>(jsonVehicle);
polymorphicVehicles.Add(aBike);
break;
default:
break;
}
}
// this is just to print it out!
var jsonPolymorphicVehicles = JsonConvert.SerializeObject(polymorphicVehicles);
Console.WriteLine("XML:");
Console.WriteLine(xml);
Console.WriteLine("");
Console.WriteLine("Polymorphic to jason");
Console.WriteLine(jsonPolymorphicVehicles);
Console.WriteLine("");
Console.WriteLine("Press key to exit!");
Console.Read();
}
}
public class Vehicle
{
public string Name = "Vehicle";
}
public class Car : Vehicle
{
public Car()
{
Name = "Car";
}
}
public class Bike : Vehicle
{
public Bike()
{
Name = "Bike";
}
}
public class Truck : Vehicle
{
public Truck()
{
Name = "Truck";
}
}
public class Vehicles
{
public List<Vehicle> Items { get; } = new List<Vehicle>();
}
public static class MyStaticClass
{
public static T XmlDeserializeFromString<T>(this string objectData)
{
return (T)XmlDeserializeFromString(objectData, typeof(T));
}
public static string XmlSerializeToString(this object objectInstance)
{
var serializer = new XmlSerializer(objectInstance.GetType());
var sb = new StringBuilder();
using (TextWriter writer = new StringWriter(sb))
{
serializer.Serialize(writer, objectInstance);
}
return sb.ToString();
}
public static object XmlDeserializeFromString(this string objectData, Type type)
{
var serializer = new XmlSerializer(type);
object result;
using (TextReader reader = new StringReader(objectData))
{
result = serializer.Deserialize(reader);
}
return result;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.