我有一个名为VehicleInfo的XML文件。 我想反序列化Vehicle List中的VehicleInfo。 现在,我有一个称为“车辆”的基本类,还有三个名为“汽车”,“自行车”,“卡车”的派生类。 如何基于xml中Vehicle节点的值反序列化车辆的特定对象。 (例如,如果节点值为Car,则应将车辆的对象存储在车辆列表中)
<Vehicles>
<Vehicle>Car</Vehicle>
<Vehicle>Bike</Vehicle>
<Vehicle>Truck</Vehicle>
</Vehicles>
例如,
VehicleList类:
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类中的Vehicle List中的特定对象(例如,汽车,自行车或卡车)。
答案 0 :(得分:1)
这里是要序列化的代码和结果。 XML不能将数组作为根元素。因此,在这种情况下,有两类是有意义的:车辆和车辆。参见下面的代码:
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>
答案 1 :(得分:0)
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);
}
}
答案 2 :(得分:0)
好,这会很长...
您可以使用此解决方案.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;
}
}