【问题标题】:Linq to XML create elements with unique parentLinq to XML 创建具有唯一父级的元素
【发布时间】:2016-11-29 18:30:57
【问题描述】:

用这个 Linq 语句创建一个 XML

new XElement(ns + "SpecialRegisters",
  from reg in registers
  where reg.IsUpdateRegister
  select new XElement(ns + "UpdateRegisters",
    new XElement(ns + "RegID",
        new XAttribute("ID", registers.IndexOf(reg).ToString().PadLeft(2, '0'))
    )
  )
)

是否可以创建具有多个 RegID 的唯一 UpdateRegisters 元素。 如果没有更新寄存器,则不应存在任何 UpdateRegisters 元素。

【问题讨论】:

  • 这个怎么样:new XElement(ns + "SpecialRegisters", registers.Where(x => x.IsUpdateRegister).Select((x,i) => new XElement(ns + "UpdateRegisters" , new XElement(ns + "RegID", new XAttribute("ID", i.ToString().PadLeft(2, '0'))))));
  • 创建超过 1 个 UpdateRegisters
  • 使用方法:ns + "UpdateRegisters" + i.ToString()

标签: c# xml linq linq-to-xml


【解决方案1】:

你可以这样做:

var result=new XElement(ns + "SpecialRegisters");
var updateRegister=register.Where(e=>e.IsUpdateRegister);// To not repeat the same query twice
if(updateRegister.Count()>0)
{
 result.Add( new XElement(ns + "UpdateRegisters", 
                          updateRegister.Select((e,i)=> new XElement(ns + "RegID",i));
}

更新

如果您想在同一个语句中完成所有操作,那么您可以这样做:

 var updateRegister=register.Where(e=>e.IsUpdateRegister);// To not repeat the same query twice
 var result=new XElement(ns + "SpecialRegisters", updateRegister.Any()?
                         new XElement(ns + "UpdateRegisters", updateRegister.Select((e,i)=> new XElement(ns + "RegID",i)):null );

我的解决方案基于你的 (miguelmpn)

速度并不重要,因为我保存的是一个简单的小文件..

new XElement(ns + "SpecialRegisters", Registers.Registers.Singleton.Any(x => x.IsUpdateRegister) ?
                     new XElement(ns + "UpdateRegisters", Registers.Registers.Singleton.Where(e => e.IsUpdateRegister).Select((e, i)=> new XElement(ns + "RegID", i))) : null)

【讨论】:

  • 这是一种解决方案,但我的目的是通过将所有代码都放在同一个 linq 查询上来保持代码更简洁。 (当然如果可能的话)
  • 恕我直言,这样做足够干净和可读。有时更好的是把你的操作分成多行。无论如何,这是在同一条语句中完成所有操作的另一种解决方案
  • 在更新查询中选择所有寄存器,我只需要选择 IsUpdateRegister 设置为 true 的那些
  • 现在它可以工作了... updateRegister 的第一步是不必要的,因为 Select() 只会创建需要的那些和 Registers.Registers.Singleton.Any(x => x.IsUpdateRegister ) 如果需要,将只创建一个 UpdateRegisters
【解决方案2】:

我认为Enumerable.Aggregate 方法重载之一非常适合这项任务。

var specialRegisters = 
new XElement(ns + "SpecialRegisters", 
             Registers.Registers.Singleton.Where(reg => reg.IsUpdateRegister)
                                          .Select((reg, i) => new XElement(ns + "RegID", i))
                                          .Aggregate(new XElement(ns + "UpdateRegisters"), 
                                                     (upReg, reg) => 
                                                     {
                                                         upReg.Add(reg);
                                                         return upReg;
                                                     }, 
                                                     upReg => upReg.HasElements ? upReg : null));

这种方法只会枚举一次集合。
Aggregate 方法的第三个参数是该方法的键值,如果没有添加任何元素,则返回null

我自己的评论意见:但我的目的是通过将代码全部放在同一个 linq 查询上来保持代码更简洁

我认为将这种逻辑保留在一个语句中是不干净的方法。我认为清洁的想法之一是阅读您的代码会更快地理解您的意图。

您可以将创建UpdateRegisters元素提取到专用方法

private XElement CreateUpdateRegistersOrNullIfEmpty(XNamespace ns,
                                                    IEnumerable<YourType> data)
{
    return data.Where(reg => reg.IsUpdateRegister)                
               .Select((reg, i) => new XElement(ns + "RegID", i))
               .Aggregate(new XElement(ns + "UpdateRegisters"), 
                          (upReg, reg) => 
                          {
                              upReg.Add(reg);
                              return upReg;
                          }, 
                          upReg => upReg.HasElements ? upReg : null));
}

那就用吧

var specialRegisters = 
    new XElement(ns + "SpecialRegisters", 
                 CreateUpdateRegistersOrNullIfEmpty(ns, Registers.Registers.Singleton));

【讨论】:

  • Aggregate 也很好用,谢谢 :) 我也在使用一种方法来保存 SpecialRegisters,我只是想避免使用 IF 语句。我认为两个遮阳篷都提供了更简单的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多