通用xml数据和xml(de)序列化?

时间:2013-08-31 13:27:40

标签: c# xml-serialization

我正在制作一个程序,它将加载一个基于xml的配置文件(不是app.config)。

在这个配置文件中,我将指定必须由程序实例化并配置的类型。

以下是我设想的一个例子:

<?xml version="1.0"?>
<configuration>
    <types>
        <type assembly="SomeAssembly.dll" class="SomeAssembly.SomeClass">
            <type-configuration>
               <address>192.168.0.1</address>
               <port>80</port>
            </type-configuration>
        </type>
    </types>
</configuration>

最内层的元素是问题,<type-configuration>。其中的元素将取决于SomeAssembly.SomeClass所需的特定配置,而不是&#34;已知&#34;到了该计划。

通过添加新类型,该部分可能如下所示:

<type assembly="SomeAssembly.dll" class="SomeAssembly.SomeClass">
    <type-configuration>
       <address>192.168.0.1</address>
       <port>80</port>
    </type-configuration>
</type>
<type assembly="SomeOtherAssembly.dll" class="SomeOtherAssembly.SomeOtherClass">
    <type-configuration>
       <url>http://www.domain.com/path/to/webpage</url>
       <authentication-token>1234567890ABC</authentication-token>
    </type-configuration>
</type>

有什么方法可以将上面的XML文件反序列化为强类型对象,并且仍然随身携带该子XML部分,以便类型本身可以将其反序列化为自己的对象?

即。我的程序的配置类可能是这样的:

[XmlType("configuration")]
public class Configuration
{
    [XmlElement("types")]
    public Collection<SubType> Types
    {
        ...
    }
}

[XmlType("type")]
public class SubType
{
    [XmlElement("configuration")]
    public ??? Configuration { get; set; }
}

如何声明SubType.Configuration属性?这甚至可能吗?

请注意,最终,该属性中的任何数据都将被赋予配置文件中指定类型的实例化对象。我还没写过那部分,所以无论做什么都行不通,

这是一个完整的LINQPad计划,可以展示我想要的内容以及我已经走了多远:

void Main()
{
    const string xml = @"<?xml version=""1.0""?>
<configuration>
    <types>
        <type assembly=""SomeAssembly.dll"" class=""SomeAssembly.SomeClass"">
            <type-configuration>
            <address>192.168.0.1</address>
            <port>80</port>
            </type-configuration>
        </type>
        <type assembly=""SomeOtherAssembly.dll"" class=""SomeOtherAssembly.SomeOtherClass"">
            <type-configuration>
            <url>http://www.domain.com/path/to/webpage</url>
            <authentication-token>1234567890ABC</authentication-token>
            </type-configuration>
        </type>
    </types>
</configuration>";

    var serializer = new XmlSerializer(typeof(Configuration));
    using (var reader = new StringReader(xml))
    {
        var configuration = (Configuration)serializer.Deserialize(reader);
        configuration.Dump();
    }
}

[XmlType("configuration")]
public class Configuration
{
    private readonly Collection<SubType> _Types = new Collection<SubType>();

    [XmlArray("types")]
    public Collection<SubType> Types
    {
        get
        {
            return _Types;
        }
    }
}

[XmlType("type")]
public class SubType
{
    private readonly Collection<XmlNode> _Configuration = new Collection<XmlNode>();

    [XmlAttribute("assembly")]
    public string AssemblyName { get; set; }

    [XmlAttribute("class")]
    public string ClassName { get; set; }

    [XmlElement("type-configuration")]
    public Collection<XmlNode> Configuration
    {
        get
        {
            return _Configuration;
        }
    }
}

这将转储两个SubType对象,但Configuration属性仅包含<type-configuration>...</type-configuration>部分的第一个子元素。将属性类型更改为string只会给我最内层的文本,即。 IP地址或网址,并将其更改为XmlDocument,与XmlNode相同。

1 个答案:

答案 0 :(得分:0)

如何使用Linq2Xml解析xml,而不是尝试使用XmlSerializer反序列化

var types = XDocument.Parse(xml)
                .Descendants("type")
                .Select(t => new SubType
                {
                    AssemblyName = t.Attribute("assembly").Value,
                    ClassName = t.Attribute("class").Value,
                    Configuration = t.Element("type-configuration")
                                     .Elements()
                                     .ToDictionary(c=>c.Name.LocalName,c=>c.Value)
                })
                .ToList();

public class SubType
{
    public string AssemblyName { get; set; }
    public string ClassName { get; set; }
    public Dictionary<string, string> Configuration { set; get; }
}