C# 基于XML结构设置类的值
我想根据对象中与XML中元素名称匹配的属性,将C# 基于XML结构设置类的值,c#,linq,reflection,C#,Linq,Reflection,我想根据对象中与XML中元素名称匹配的属性,将XML字符串中的某些元素处理为对象 XML的示例结构如下: <Bar> <Body> <Header> <A>Value</A> <B>true</B> </Header> <Data> <D>Value</D> </Data>
XML
字符串中的某些元素处理为对象
XML
的示例结构如下:
<Bar>
<Body>
<Header>
<A>Value</A>
<B>true</B>
</Header>
<Data>
<D>Value</D>
</Data>
<Data>
<D>Value2</D>
<Data>
</Body>
</Bar>
如果您的XML真的那么简单,那么您可以使用序列化来获得这种动态/自加载行为,方法是使用适当的方法来装饰模型类,尽管文档中的每个缩进级别至少需要1个类:
void Main()
{
var xml = @"<Bar>
<Body>
<Header>
<A>Value</A>
<B>true</B>
</Header>
<Data>
<D>Value</D>
</Data>
<Data>
<D>Value2</D>
</Data>
</Body>
</Bar>";
var serializer = new XmlSerializer(typeof(Bar));
serializer.Deserialize( new MemoryStream( Encoding.ASCII.GetBytes( xml ) ) ).Dump();
}
public class Bar
{
public Body Body { get; set; }
}
public class Body
{
public Header Header { get; set; }
[XmlElement]
public Data[] Data { get; set; }
}
public class Header
{
public string A { get; set; }
public string B { get; set; }
}
public class Data
{
public string D { get; set; }
}
void Main()
{
var xml=@”
价值
真的
价值
价值2
";
var serializer=新的XmlSerializer(typeof(Bar));
反序列化(新的MemoryStream(Encoding.ASCII.GetBytes(xml))).Dump();
}
公共类酒吧
{
公共机构主体{get;set;}
}
公共阶级团体
{
公共标头{get;set;}
[XmlElement]
公共数据[]数据{get;set;}
}
公共类标题
{
公共字符串A{get;set;}
公共字符串B{get;set;}
}
公共类数据
{
公共字符串D{get;set;}
}
(Edited:我忽略了只有一个Header元素)如果您的XML真的那么简单,您可以使用序列化来获得这种动态/自加载行为,方法是使用适当的样式来装饰您的模型类,尽管文档中每个缩进级别至少需要一个类:
void Main()
{
var xml = @"<Bar>
<Body>
<Header>
<A>Value</A>
<B>true</B>
</Header>
<Data>
<D>Value</D>
</Data>
<Data>
<D>Value2</D>
</Data>
</Body>
</Bar>";
var serializer = new XmlSerializer(typeof(Bar));
serializer.Deserialize( new MemoryStream( Encoding.ASCII.GetBytes( xml ) ) ).Dump();
}
public class Bar
{
public Body Body { get; set; }
}
public class Body
{
public Header Header { get; set; }
[XmlElement]
public Data[] Data { get; set; }
}
public class Header
{
public string A { get; set; }
public string B { get; set; }
}
public class Data
{
public string D { get; set; }
}
void Main()
{
var xml=@”
价值
真的
价值
价值2
";
var serializer=新的XmlSerializer(typeof(Bar));
反序列化(新的MemoryStream(Encoding.ASCII.GetBytes(xml))).Dump();
}
公共类酒吧
{
公共机构主体{get;set;}
}
公共阶级团体
{
公共标头{get;set;}
[XmlElement]
公共数据[]数据{get;set;}
}
公共类标题
{
公共字符串A{get;set;}
公共字符串B{get;set;}
}
公共类数据
{
公共字符串D{get;set;}
}
(已编辑:我忽略了只有一个标题元素)我使用了与标题类似的行,因为没有简单的方法将其合并为一行
var dataElements = (from dataDescendants in (from ele2 in xDoc.Descendants()
Where ele2.Name.LocalName == "Data"
select ele2.Descendants())
from dataDescendant in dataDescendants
join prop in typeof(FooItem).GetProperties() on prop.Name equals dataDescendant.Name.LocalName
select Element = dataDescendant, Property = prop, dataDescendants
group by dataDescendants into g = group
select g).ToList();
dataElements.ForEach(dataElement =>
{
FooItem fi = new FooItem();
dataElement.ToList.ForEach(x =>
{
object objVal = null;
x.Property.PropertyType.TryParse(x.Element.Value, objVal);
x.Property.SetValue(fi, objVal, null);
}
DataItems.Add(fi);
}
我使用了与标题类似的行,因为没有一种简单的方法将其合并到一行中
var dataElements = (from dataDescendants in (from ele2 in xDoc.Descendants()
Where ele2.Name.LocalName == "Data"
select ele2.Descendants())
from dataDescendant in dataDescendants
join prop in typeof(FooItem).GetProperties() on prop.Name equals dataDescendant.Name.LocalName
select Element = dataDescendant, Property = prop, dataDescendants
group by dataDescendants into g = group
select g).ToList();
dataElements.ForEach(dataElement =>
{
FooItem fi = new FooItem();
dataElement.ToList.ForEach(x =>
{
object objVal = null;
x.Property.PropertyType.TryParse(x.Element.Value, objVal);
x.Property.SetValue(fi, objVal, null);
}
DataItems.Add(fi);
}
方法
prop.PropertyType.TryParse
从何而来?@mipe34抱歉,这是一个扩展方法,您希望我包含代码吗?是的,这将帮助我尝试您的代码;-)@mipe34我现在已经使用了它,所以不必担心和浪费您的时间:)好的,但是如果您可以发布解决方案,那就太好了。这是一个有趣的问题。该方法prop.PropertyType.TryParse
从何而来?@mipe34抱歉,这是一个扩展方法,您希望我包含代码吗?是的,它将帮助我尝试您的代码;-)@mipe34我现在已经使用了它,所以不必担心和浪费您的时间:)好的,但是如果您可以发布解决方案,那就太好了。这是一个有趣的问题。