簡體   English   中英

.NET序列化為XML。 如何為數組類型設置別名?

[英].NET serialization of Array to XML. How to set an alias for array type?

我試圖找出.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<Person[]>(p);
        }

        static void SerializeObject<T>(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內容:

<ArrayOfPerson>
  <Person>
    <Firstname>Michael</Firstname>
    <Lastname>Jackson</Lastname>
    <Age>20</Age>
  </Person>
  <Person>
    <Firstname>Bill</Firstname>
    <Lastname>Gates</Lastname>
    <Age>21</Age>
  </Person>
  <Person>
    <Firstname>Steve</Firstname>
    <Lastname>Jobs</Lastname>
    <Age>22</Age>
  </Person>
</ArrayOfPerson>

但這不是我想要的。 我希望它看起來像這樣:

<Persons>
  <Person>
    <Firstname>Michael</Firstname>
    <Lastname>Jackson</Lastname>
    <Age>20</Age>
  </Person>
  <Person>
    <Firstname>Bill</Firstname>
    <Lastname>Gates</Lastname>
    <Age>21</Age>
  </Person>
  <Person>
    <Firstname>Steve</Firstname>
    <Lastname>Jobs</Lastname>
    <Age>22</Age>
  </Person>
</Persons>

我怎么能這樣工作呢? 提前致謝!

除了已經提供的建議之外,您只需對代碼進行一些小的更改。

首先,需要重新聲明SerializeObject泛型方法:

// important: declare the input parameter to be an **array** of T, not T.
static void SerializeObject<T>(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 
        // (e.g., 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<Person[]>(p)替換為SerializeObject<Person>(p) 因此,您的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<Person>(p);
}

生成的XML將如下所示:

<Persons>
  <Person>
    <Firstname>Michael</Firstname>
    <Lastname>Jackson</Lastname>
    <Age>20</Age>
  </Person>
  <Person>
    <Firstname>Bill</Firstname>
    <Lastname>Gates</Lastname>
    <Age>21</Age>
  </Person>
  <Person>
    <Firstname>Steve</Firstname>
    <Lastname>Jobs</Lastname>
    <Age>22</Age>
  </Person>
</Persons>

要將<Person>元素名稱覆蓋為其他名稱,請在類上設置XmlType屬性,如下所示:

[XmlType("personEntry")]
public class Person
{
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public uint Age { get; set; }
}

生成的XML如下所示:

<Persons>
  <personEntry>
    <Firstname>Michael</Firstname>
    <Lastname>Jackson</Lastname>
    <Age>20</Age>
  </personEntry>
  <personEntry>
    <Firstname>Bill</Firstname>
    <Lastname>Gates</Lastname>
    <Age>21</Age>
  </personEntry>
  <personEntry>
    <Firstname>Steve</Firstname>
    <Lastname>Jobs</Lastname>
    <Age>22</Age>
  </personEntry>
</Persons>

你需要一個像這樣的容器類:

    /// <summary>
    /// Represents an Person collection.
    /// </summary>
    [Serializable]
    [XmlRoot("Persons", IsNullable = false)]
    public sealed class Persons
    {
        /// <summary>
        /// The person collection.
        /// </summary>
        private Collection<Person> persons;

        /// <summary>
        /// Initializes a new instance of the <see cref="Persons"/> class.
        /// </summary>
        /// <param name="persons">The person list.</param>
        public Persons(Collection<Person> persons)
        {
            this.persons = persons;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Persons"/> class.
        /// </summary>
        /// <param name="persons">The person array.</param>
        public Persons(Person[] persons)
            : this(new Collection<Person>(persons))
        {
        }

        /// <summary>
        /// Prevents a default instance of the <see cref="Persons"/> class from being created.
        /// </summary>
        private Persons()
        {
        }

        /// <summary>
        /// Copies the collection of Person objects to an array and returns
        /// it.
        /// </summary>
        /// <returns>An array of Person objects based on the
        /// collection.</returns>
        public Person[] ToArray()
        {
            Person[] personArray = new Person[this.persons.Count];

            this.persons.CopyTo(personArray, 0);
            return personArray;
        }

        /// <summary>
        /// Gets or sets the persons.
        /// </summary>
        /// <value>The persons.</value>
        [XmlElement("Person")]
        public Collection<Person> ThePersons
        {
            get
            {
                return this.persons;
            }

            set
            {
                this.persons = value;
            }
        }

        /// <summary>
        /// Gets the length of the persons.
        /// </summary>
        /// <value>The length of the persons.</value>
        [XmlIgnore]
        public int Length
        {
            get
            {
                return this.persons.Count;
            }
        }

        /// <summary>
        /// Returns an enumerator that iterates through the collection.
        /// </summary>
        /// <returns>A <see cref="IEnumerator&lt;Person&gt;"/> that can be used to
        /// iterate through the collection.</returns>
        public IEnumerator<Person> GetEnumerator()
        {
            return (IEnumerator<Person>)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<Persons>(new Persons(p));

        Person[] p2 = DeserializeObject<Persons>("filename.xml").ToArray();
    }

解串器方法非常簡單:

    static T DeserializeObject<T>(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>(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<Person[]>(p, typeof(Person));

您可以通過向序列化程序添加root屬性來實現。 見下文。

 static void SerializeObject<T>(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);
        }
    }

或者,您可以傳入一個名稱選擇的func。 你的代碼就是

 SerializeObject<Person[]>(p, per=>p.GetType().Name);



static void SerializeObject<T>(T obj, Func<T,string> 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);
    }
}

此外,通過Attributes控制序列化的這個鏈接對我來說一直很有用。

http://msdn.microsoft.com/en-us/library/2baksw0z(v=VS.100).aspx

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM