我正在制作一个程序,它将加载一个基于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
相同。
答案 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; }
}