我如何在这里阅读完整的XML元素?

时间:2015-10-07 21:19:49

标签: c# wpf linq

我有一个包含Unit s:

的XML文件
<Unit Name="Length">
<Prefix Char="c"
          IsSelected="false"
          Factor="1"/>

<Prefix Char="d"
          IsSelected="true"
          Factor="104"/>
</Unit>

我想读一整个对象:

public static Dictionary<string, Unit> Units { get; set; } 
public class Prefix
{
    public Func<double, double> fnc = null;            
    public Prefix(string c, double f, bool i, bool ifix = false,string fn = null)
    {
        Char = c;
        Factor = f;
        IsFixed = ifix;
        Unit.funcs.TryGetValue(fn, out fnc);
    }

     public bool IsSelected { get; set; }
     public bool IsFixed { get; set; }
     public double Factor { get; set; }
     public string Char { get; set; }

}

public Unit() { }
public Unit(string n, List<Prefix> p)
{
    _name = n;
    Prefixes = p;
}

 private List<Prefix> _prefixes;
 public List<Prefix> Prefixes
 {
     get { return _prefixes; }
     set { _prefixes = value;  }
 }
 private string _name;
 public string Name
 { 
    get { return _name; }
    set { _name = value; }
 }
  ....
 }

我现在有了这个:

 Form.Units = (data.Descendants("Unit").Select(x => new Unit
                     (
                        x.Attribute("Name").Value,
                        (List<Prefix>) x.Descendants("Prefix").Select(p => new Prefix(
                            p.Attribute("Char").Value,
                            Convert.ToDouble(p.Attribute("Factor").Value),
                            p.Attribute("IsSelected").Value == "true",
                            p.Attribute("IsFixed").Value == "true",
                            p.Attribute("Func").Value)
                         )
                      )
                    )
               ).ToDictionary(x => x.Name, x => x);

并收到以下错误:

  

“无法转换类型的对象   'WhereSelectEnumerableIterator 2[System.Xml.Linq.XElement,DD.Prefix]' to type 'System.Collections.Generic.List 1 [DD.Prefix]'。“

显然(List<Prefix>)

有问题

那么查询必须是什么?如何在List&lt;&gt;?

中获取内容

3 个答案:

答案 0 :(得分:1)

它不是一个列表,而是一个查询,所以你不能只将它转换为一个列表,但你可以调用它上面的ToList来枚举它并返回一个列表:

 Form.Units = (data.Descendants("Unit").Select(x => new Unit
                 (
                    x.Attribute("Name").Value,
                    //(List<Prefix>) no casting needed
                    x.Descendants("Prefix").Select(p => new Prefix(
                        p.Attribute("Char").Value,
                        Convert.ToDouble(p.Attribute("Factor").Value),
                        p.Attribute("IsSelected").Value == "true",
                        p.Attribute("IsFixed").Value == "true",
                        p.Attribute("Func").Value)
                     ).ToList() // you had an IEnumerable<Prefix> now this is a List<Prefix>
                  )
                )
           ).ToDictionary(x => x.Name, x => x);

答案 1 :(得分:1)

为了扩展我的评论,这里有几件事。首先,您可以使用.ToList()上的.Select扩展程序将IEnumerable<T>集合转换为List<T>

其次,如果查询中缺少任何属性或元素,您将获得空引用异常。您可以通过显式转换为string(然后根据需要转换结果)安全地处理此问题。

更新后的查询如下所示:

Form.Units = (data.Descendants("Unit").Select(x => new Unit
    ((string)x.Attribute("Name"),
     x.Descendants("Prefix").Select(p => new Prefix(
         (string)p.Attribute("Char"),
         Convert.ToDouble((string)p.Attribute("Factor")),
         (string)p.Attribute("IsSelected") == "true",
         (string)p.Attribute("IsFixed") == "true",
         (string)p.Attribute("Func")).ToList()
      )
    )
)
).ToDictionary(x => x.Name, x => x);

请注意,在使用.Value时,您不需要(string)(因为.Value已经string)。

答案 2 :(得分:1)

我将以下列方式表达此代码..因为它避免了将参数构造函数限制为将这些类型约束为IEnuermable表达式。即避免在计划用于查询的类型上执行参数构造函数。

我将Decendents中使用的类型设置为XmlElement类型...但我确定这是不准确的......只需将其替换即可无论什么是正确的类型。

此外,此代码段并未考虑Unit.funcs.TryGetValue(fn, out fnc); ..并且它假定Func类型上有属性名称Prefix。您可以在分配/设置期间执行空检查。

data.Descendants("Unit")
                .Select<XmlElement, Unit>(x => new Unit() 
                { 
                    Name = x.Attribute("Name").Value,
                    Prefixes = x.Descendants("Prefix").Select<XmlElement, Prefix>(p => new Prefix() 
                    {
                        Char = p.Attribute("Char").Value,
                        Factor = Convert.ToDouble(p.Attribute("Factor").Value),
                        IsSelectd = p.Attribute("IsSelected").Value == "true",
                        IsFixed = p.Attribute("IsFixed").Value == "true",
                        Func = p.Attribute("Func").Value
                    }).ToList()
                })
                .Select<Unit, KeyValuePair<string, Unit>>(unit => new KeyValuePair<string, Unit>() 
                {
                    Key = x.Name,
                    Value = x 
                })
                .ToList()
                .ForEach( kvp => {
                    Form.Units.Add(kvp.Key, kvp.Value);
                });