.NET序列化为XML。 如何为数组类型设置别名?
我试图找出.net数组到XML的序列化。 这是我提出的一段代码:
public class Program { public class Person { public string Firstname { get; set; } public string Lastname { get; set; } public uint Age { get; set; } } static void Main () { Person[] p = { new Person{Age = 20, Firstname = "Michael", Lastname = "Jackson"}, new Person{Age = 21, Firstname = "Bill", Lastname = "Gates"}, new Person{Age = 22, Firstname = "Steve", Lastname = "Jobs"} }; SerializeObject(p); } static void SerializeObject(T obj) where T : class { string fileName = Guid.NewGuid().ToString().Replace("-", "") + ".xml"; using (FileStream fs = File.Create(fileName)) { XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", ""); XmlSerializer ser = new XmlSerializer(typeof(T)); ser.Serialize(fs, obj, ns); } } }
以下是此示例写入XML文件的XML内容:
Michael Jackson 20 Bill Gates 21 Steve Jobs 22
但这不是我想要的。 我希望它看起来像这样:
Michael Jackson 20 Bill Gates 21 Steve Jobs 22
我怎么能这样工作呢? 提前致谢!
除了已经提供的建议之外,您只需对代码进行一些小的更改。
首先,需要重新声明SerializeObjectgenerics方法:
// important: declare the input parameter to be an **array** of T, not T. static void SerializeObject(T[] obj) where T : class { string fileName = Guid.NewGuid().ToString().Replace("-", "") + ".xml"; using (FileStream fs = File.Create(fileName)) { XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", ""); // override default root node name. based on your question, // i'm just going to append an "s" to the base type // (eg, Person becomes Persons) var rootName = typeof(T).Name + "s"; XmlRootAttribute root = new XmlRootAttribute(rootName); // add the attribute to the serializer constructor... XmlSerializer ser = new XmlSerializer(obj.GetType(), root); ser.Serialize(fs, obj, ns); } }
其次,在Main()方法中,将SerializeObject
替换为SerializeObject
。 因此,您的Main()方法将如下所示:
static void Main(string[] args) { Person[] p = { new Person{Age = 20, Firstname = "Michael", Lastname = "Jackson"}, new Person{Age = 21, Firstname = "Bill", Lastname = "Gates"}, new Person{Age = 22, Firstname = "Steve", Lastname = "Jobs"} }; SerializeObject(p); }
生成的XML将如下所示:
Michael Jackson 20 Bill Gates 21 Steve Jobs 22
要将
元素名称覆盖为其他名称,请在类上设置XmlType
属性,如下所示:
[XmlType("personEntry")] public class Person { public string Firstname { get; set; } public string Lastname { get; set; } public uint Age { get; set; } }
生成的XML如下所示:
Michael Jackson 20 Bill Gates 21 Steve Jobs 22
你需要一个像这样的容器类:
/// /// Represents an Person collection. /// [Serializable] [XmlRoot("Persons", IsNullable = false)] public sealed class Persons { /// /// The person collection. /// private Collection persons; /// /// Initializes a new instance of the class. /// /// The person list. public Persons(Collection persons) { this.persons = persons; } /// /// Initializes a new instance of the class. /// /// The person array. public Persons(Person[] persons) : this(new Collection (persons)) { } /// /// Prevents a default instance of the class from being created. /// private Persons() { } /// /// Copies the collection of Person objects to an array and returns /// it. /// /// An array of Person objects based on the /// collection. public Person[] ToArray() { Person[] personArray = new Person[this.persons.Count]; this.persons.CopyTo(personArray, 0); return personArray; } /// /// Gets or sets the persons. /// /// The persons. [XmlElement("Person")] public Collection ThePersons { get { return this.persons; } set { this.persons = value; } } /// /// Gets the length of the persons. /// /// The length of the persons. [XmlIgnore] public int Length { get { return this.persons.Count; } } /// /// Returns an enumerator that iterates through the collection. /// /// A that can be used to /// iterate through the collection. public IEnumerator GetEnumerator() { return (IEnumerator )this.persons.GetEnumerator(); } }
使用完成的数组初始化它并按照Main()
方法返回它:
static void Main () { Person[] p = { new Person{Age = 20, Firstname = "Michael", Lastname = "Jackson"}, new Person{Age = 21, Firstname = "Bill", Lastname = "Gates"}, new Person{Age = 22, Firstname = "Steve", Lastname = "Jobs"} }; SerializeObject(new Persons(p)); Person[] p2 = DeserializeObject ("filename.xml").ToArray(); }
解串器方法非常简单:
static T DeserializeObject(string fileName) where T : class { using (FileStream fs = File.OpenRead(fileName)) { XmlSerializer ser = new XmlSerializer(typeof(T)); return (T)ser.Deserialize(fs); } }
选项2(基于Nix的回答 ):
static void SerializeObject(T obj, Type t) where T : class { string fileName = Guid.NewGuid().ToString().Replace("-", "") + ".xml"; using (FileStream fs = File.Create(fileName)) { XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", ""); XmlRootAttribute root = new XmlRootAttribute(t.Name + "s"); XmlSerializer ser = new XmlSerializer(typeof(T), root); ser.Serialize(fs, obj, ns); } }
可以这样称呼:
SerializeObject(p, typeof(Person));
此外,通过Attributes控制序列化的这个链接对我来说一直很有用。
http://msdn.microsoft.com/en-us/library/2baksw0z(v=VS.100).aspx
您可以通过向序列化程序添加root属性来完成此操作。 见下文。
static void SerializeObject(T obj) where T : class { string fileName = Guid.NewGuid().ToString().Replace("-", "") + ".xml"; using (FileStream fs = File.Create(fileName)) { XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", ""); XmlRootAttribute root = new XmlRootAttribute( typeof(T).Name + "s"); XmlSerializer ser = new XmlSerializer(typeof(Person[]), root); ser.Serialize(fs, obj, ns); } }
或者,您可以传入一个选择名称的函数。 你的代码就是
SerializeObject(p, per=>p.GetType().Name); static void SerializeObject(T obj, Func nameSelector) where T : class { string fileName = Guid.NewGuid().ToString().Replace("-", "") + ".xml"; using (FileStream fs = File.Create(fileName)) { XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); ns.Add("", ""); XmlRootAttribute root = new XmlRootAttribute(nameSelector(obj)); XmlSerializer ser = new XmlSerializer(typeof(Person[]), root); ser.Serialize(fs, obj, ns); } }