C# 基于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
字符串中的某些元素处理为对象

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我现在已经使用了它,所以不必担心和浪费您的时间:)好的,但是如果您可以发布解决方案,那就太好了。这是一个有趣的问题。