You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# 如何使用泛型反序列化动态XML?附常规实现示例

Generic XML Deserialization in C# for Dynamic Scenarios

First off, your existing strongly-typed deserialization works great for fixed XML structures, but a generic approach can make this logic reusable across different schemas. Depending on what you mean by "dynamic," here are two practical, actionable solutions:

1. Reusable Generic Deserialization Method (Strongly-Typed)

If you still want to define model classes for your XML structures but avoid repeating deserialization boilerplate, a generic helper method is perfect. It lets you deserialize any XML into its corresponding strongly-typed class with a single call.

Implementation:

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

public static class XmlSerializationHelper
{
    // Generic method to deserialize any XML string into a specified type
    public static T Deserialize<T>(string xml) where T : class
    {
        if (string.IsNullOrEmpty(xml))
            throw new ArgumentNullException(nameof(xml));

        var serializer = new XmlSerializer(typeof(T));
        using var stringReader = new StringReader(xml);
        
        return (T)serializer.Deserialize(stringReader);
    }

    // Optional: Generic serialization method for round-tripping data
    public static string Serialize<T>(T obj) where T : class
    {
        if (obj == null)
            throw new ArgumentNullException(nameof(obj));

        var serializer = new XmlSerializer(typeof(T));
        using var stringWriter = new StringWriter();
        
        serializer.Serialize(stringWriter, obj);
        return stringWriter.ToString();
    }
}

Usage with Your Existing Model:

You can use this helper with your existing Response and Results classes seamlessly:

string xml = @"<RESPONSE version=""10""> <RESULTS MyAttribute=""1"" /> </RESPONSE>";

// Deserialize into your strongly-typed Response class
var response = XmlSerializationHelper.Deserialize<Response>(xml);

// Access the attribute value
bool attributeValue = response.Results.MyAttribute;

This approach keeps type safety while making deserialization logic reusable across all your XML models.

2. Dynamic Generic Structure for Arbitrary XML

If you need to handle frequently changing XML structures (without pre-defining model classes), create a generic, flexible container class that captures attributes, child elements, and text content dynamically.

Implementation:

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

[XmlRoot]
public class DynamicXmlNode<T> where T : class, new()
{
    // Capture all attributes in a list (for easy access)
    [XmlAnyAttribute]
    public List<System.Xml.XmlAttribute> Attributes { get; set; } = new();

    // Capture any child elements (recursive generic structure)
    [XmlAnyElement]
    public List<DynamicXmlNode<object>> ChildNodes { get; set; } = new();

    // Capture text content if present
    [XmlText]
    public string TextContent { get; set; }

    // Optional: Strongly-typed content to mix dynamic and static logic
    public T TypedContent { get; set; } = new();

    // Helper method to get an attribute value by name
    public string GetAttributeValue(string attributeName)
    {
        return Attributes.FirstOrDefault(a => a.Name == attributeName)?.Value;
    }
}

Usage:

For your sample XML, you can deserialize into this dynamic structure and access elements/attributes without pre-defined classes:

string xml = @"<RESPONSE version=""10""> <RESULTS MyAttribute=""1"" /> </RESPONSE>";

var dynamicNode = XmlSerializationHelper.Deserialize<DynamicXmlNode<object>>(xml);

// Get the root element's version attribute
string version = dynamicNode.GetAttributeValue("version");

// Find the RESULTS child node and get its MyAttribute value
var resultsNode = dynamicNode.ChildNodes.First(n => n.LocalName == "RESULTS");
bool myAttributeBool = bool.Parse(resultsNode.GetAttributeValue("MyAttribute"));

This approach gives you full flexibility to handle any XML structure dynamically while using generics for type consistency in your container.

Bonus: Fully Dynamic ExpandoObject Approach

If you want ultimate flexibility without generics, combine the helper method with ExpandoObject to get a fully dynamic object where you can access properties directly:

using System.Dynamic;
using System.Xml;

public static dynamic DeserializeToDynamic(string xml)
{
    var doc = new XmlDocument();
    doc.LoadXml(xml);
    return ConvertXmlNodeToExpando(doc.DocumentElement);
}

private static dynamic ConvertXmlNodeToExpando(XmlNode node)
{
    var expando = new ExpandoObject() as IDictionary<string, object>;

    // Add all attributes to the expando object
    foreach (XmlAttribute attr in node.Attributes)
    {
        expando[attr.Name] = attr.Value;
    }

    // Add child nodes
    foreach (XmlNode childNode in node.ChildNodes)
    {
        if (childNode is XmlElement element)
        {
            if (!expando.ContainsKey(element.Name))
                expando[element.Name] = new List<dynamic>();
            
            ((List<dynamic>)expando[element.Name]).Add(ConvertXmlNodeToExpando(element));
        }
        else if (childNode is XmlText textNode && !string.IsNullOrWhiteSpace(textNode.Value))
        {
            expando["TextContent"] = textNode.Value;
        }
    }

    return expando;
}

Usage:

dynamic dynamicResponse = DeserializeToDynamic(xml);
string version = dynamicResponse.version;
bool myAttribute = bool.Parse(dynamicResponse.RESULTS[0].MyAttribute);

This lets you interact with the XML as if it were a native C# object, no model classes required.


内容的提问来源于stack exchange,提问作者JOSEFtw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:02:22