首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

C# XML 序列化深度解析:XmlSerializer、特性控制、異常處理與最佳實踐(附完整代碼)

     編輯:PHP 綜合知識

前言

本文針對 C# System.Xml.Serialization.XmlSerializer 進行系統講解,涵蓋基本用法、特性控制序列化行為、異常處理模式、大對象圖優化,並提供可直接運行的控制台示例。注意:此為 C# 技術內容,非 PHP。

核心類與命名空間

  • System.Xml.Serialization.XmlSerializer:核心序列化器
  • System.Xml.Serialization.* 特性:XmlRoot、XmlElement、XmlAttribute、XmlIgnore、XmlArray、XmlArrayItem 等
  • System.IO.StringReader/Writer、MemoryStream、XmlTextWriter:流操作

基礎模型定義

using System;
using System.Collections.Generic;
using System.Xml.Serialization;

public class Member
{
    [XmlElement("Member_Num")] // 控制元素名
    public string Num { get; set; }
    
    public string Name { get; set; }
}

[XmlRoot("Our_Team")] // 控制根元素名
public class Team
{
    [XmlIgnore] // 忽略此屬性,不序列化
    public string InternalCode { get; set; }
    
    [XmlAttribute("team_name")] // 序列化為屬性而非元素
    public string Name { get; set; }
    
    [XmlArray("Members")]
    [XmlArrayItem("Member")]
    public List<Member> Members { get; set; } = new();
}

通用序列化/反序列化輔助類

using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

public static class XmlHelper
{
    /// <summary>
    /// 對象序列化為 XML 字符串(UTF-8 無 BOM,縮進格式化)
    /// </summary>
    public static string Serialize<T>(T obj, string rootName = null) where T : class
    {
        if (obj == null) return string.Empty;
        
        var serializer = new XmlSerializer(typeof(T), rootName != null ? new XmlRootAttribute(rootName) : null);
        var settings = new XmlWriterSettings
        {
            Encoding = new UTF8Encoding(false), // 無 BOM
            Indent = true,
            IndentChars = "  ",
            OmitXmlDeclaration = false
        };
        
        using var ms = new MemoryStream();
        using (var writer = XmlWriter.Create(ms, settings))
        {
            serializer.Serialize(writer, obj);
        }
        return Encoding.UTF8.GetString(ms.ToArray());
    }
    
    /// <summary>
    /// XML 字符串反序列化為對象
    /// </summary>
    public static T Deserialize<T>(string xml) where T : class
    {
        if (string.IsNullOrWhiteSpace(xml)) return null;
        
        var serializer = new XmlSerializer(typeof(T));
        using var reader = new StringReader(xml);
        return (T)serializer.Deserialize(reader);
    }
    
    /// <summary>
    /// 文件級序列化/反序列化
    /// </summary>
    public static void SerializeToFile<T>(T obj, string filePath) where T : class
    {
        var xml = Serialize(obj);
        File.WriteAllText(filePath, xml, new UTF8Encoding(false));
    }
    
    public static T DeserializeFromFile<T>(string filePath) where T : class
    {
        var xml = File.ReadAllText(filePath, Encoding.UTF8);
        return Deserialize<T>(xml);
    }
}

控制台演示程序

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // 構建對象圖
        var team = new Team
        {
            Name = "Development",
            InternalCode = "DEV-001", // 將被忽略
            Members = new List<Member>
            {
                new Member { Num = "001", Name = "Marry" },
                new Member { Num = "002", Name = "John" }
            }
        };
        
        // 序列化
        string xml = XmlHelper.Serialize(team);
        Console.WriteLine("=== 序列化結果 ===");
        Console.WriteLine(xml);
        
        /*
        輸出:
        <?xml version="1.0" encoding="utf-8"?>
        <Our_Team team_name="Development">
          <Members>
            <Member>
              <Member_Num>001</Member_Num>
              <Name>Marry</Name>
            </Member>
            <Member>
              <Member_Num>002</Member_Num>
              <Name>John</Name>
            </Member>
          </Members>
        </Our_Team>
        */
        
        // 反序列化
        var newTeam = XmlHelper.Deserialize<Team>(xml);
        Console.WriteLine("\n=== 反序列化驗證 ===");
        Console.WriteLine($"Team Name: {newTeam.Name}"); // Development
        Console.WriteLine($"InternalCode: {newTeam.InternalCode}"); // null (被忽略)
        foreach (var m in newTeam.Members)
        {
            Console.WriteLine($"  {m.Num} - {m.Name}");
        }
        
        // 文件操作演示
        XmlHelper.SerializeToFile(team, "team.xml");
        var fromFile = XmlHelper.DeserializeFromFile<Team>("team.xml");
        Console.WriteLine($"\n文件讀取: {fromFile.Name}");
    }
}

特性控制大全

特性作用目標效果示例
XmlRoot類根元素名、命名空間[XmlRoot("Data", Namespace="https://ns")]
XmlElement屬性/字段子元素名、類型、順序、命名空間[XmlElement("Item", Order=1)]
XmlAttribute屬性/字段序列化為 XML 屬性[XmlAttribute("id")]
XmlIgnore屬性/字段完全跳過[XmlIgnore] public string Pwd;
XmlArray集合屬性父數組元素名[XmlArray("Users")]
XmlArrayItem集合屬性子元素名、類型[XmlArrayItem("User", Type=typeof(User))]
XmlText單一屬性作為元素文本內容[XmlText] public string Content;
XmlEnum枚舉字段自定義枚舉值的 XML 表示[XmlEnum("ACTIVE")] Active = 1
XmlInclude類包含衍生類型(多態序列化)[XmlInclude(typeof(Derived))]

進階主題

1. 多態序列化(XmlInclude)

[XmlInclude(typeof(Car))]
[XmlInclude(typeof(Bike))]
public abstract class Vehicle { public string Brand; }

public class Car : Vehicle { public int Doors; }
public class Bike : Vehicle { public bool HasBasket; }

// 序列化 List<Vehicle> 時能正確識別 Car/Bike 類型
var vehicles = new List<Vehicle> { new Car { Brand="Toyota", Doors=4 }, new Bike { Brand="Giant", HasBasket=true } };

2. 自定義序列化邏輯(IXmlSerializable)

public class CustomData : IXmlSerializable
{
    public Dictionary<string, string> Data { get; set; }
    
    public System.Xml.Schema.XmlSchema GetSchema() => null;
    
    public void ReadXml(XmlReader reader)
    {
        reader.ReadStartElement();
        while (reader.NodeType != XmlNodeType.EndElement)
        {
            var key = reader.Name;
            reader.ReadStartElement();
            var value = reader.ReadContentAsString();
            Data[key] = value;
            reader.ReadEndElement();
        }
        reader.ReadEndElement();
    }
    
    public void WriteXml(XmlWriter writer)
    {
        foreach (var kv in Data)
        {
            writer.WriteElementString(kv.Key, kv.Value);
        }
    }
}

3. 性能優化:序列化器緩存

XmlSerializer 構造函數會動態生成程序集,**必須緩存實例**,否則嚴重洩漏內存:

// 靜態緩存字典
private static readonly Dictionary<Type, XmlSerializer> _cache = new();

public static XmlSerializer GetSerializer(Type type)
{
    lock (_cache)
    {
        if (!_cache.TryGetValue(type, out var serializer))
        {
            serializer = new XmlSerializer(type);
            _cache[type] = serializer;
        }
        return serializer;
    }
}

4. 異常處理最佳實踐

try
{
    var obj = XmlHelper.Deserialize<Team>(xml);
}
catch (InvalidOperationException ex) when (ex.InnerException is XmlException xmlEx)
{
    // XML 格式錯誤:xmlEx.LineNumber, xmlEx.LinePosition
    logger.LogError(xmlEx, "XML 解析失敗");
    throw new BusinessException("數據格式錯誤", ex);
}
catch (Exception ex)
{
    logger.LogError(ex, "反序列化異常");
    throw;
}

總結

C# XmlSerializer 是功能強大、標準化的 XML 處理工具。掌握特性控制、序列化器緩存、異常處理、多態支持,即可應對企業級 XML 集成場景。現代 .NET 也可考慮 System.Text.Json (JSON) 或 YamlDotNet (YAML) 作為替代格式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved