有没有办法简化Linq新对象初始化的初始化?

时间:2016-02-18 18:12:13

标签: c# linq

我发现我在Linq查询中重复了很多新的对象初始化代码,例如在创建使用相同查询结构的不同重载方法时。

var result = ItemResponses
    .GroupBy(ir => ir.ItemID)
    .Select(
        grouped => new 
        {
            ItemID = grouped.Key,
            Average = (double)grouped.Average(g => g.OptionValue),
            ...etc. lots of properties, similar structure across lots of methods...
            ...Would really love to be able to write this code once somewhere...
        }
    );

起初我认为使用构造函数可能是这样做的一种方式,具体如下:

var result = ItemResponses
    .GroupBy(ir => ir.ItemID)
    .Select(grouped => new TestClass(grouped)   //or anonymous type
    );

public class TestClass
{
    public int ItemID { get; set; }
    public double Average { get; set; }

    public TestClass() {}

    public TestClass(IGrouping<int, ItemRespons> values)
    {
        ItemID = values.Key;
        Average = values.Average(g => g.OptionValue);
    }   
}

但是我看到Linq(至少对于Entities)只允许无参数构造函数和初始化器。所以这种方法似乎不起作用。

我是否有另一种方法可以简化这种类型的重复代码,只将它放在一个地方?

2 个答案:

答案 0 :(得分:1)

使用delegate

Func<IQueryable<ItemResponse>,IEnumerable<TestClass>> SelectResult = q => 
q.GroupBy(ir => ir.ItemID)
 .Select(
     grouped => new TestClass
     {
         ItemID = grouped.Key,
         Average = (double)grouped.Average(g => g.OptionValue),
         ...
     });

然后你可以像这样使用它:

var result = SelectResult(ctx.ItemResponse);

当然,将它作为一种扩展方法更好:

public static class Extensions
{
   public static IEnumerable<TestClass> SelectResult(this IQueryable<ItemResponse> q)
   {
      return q.GroupBy(ir => ...)
   }
}

并像这样使用它:

var result = ctx.ItemResponses.SelectResult();

答案 1 :(得分:1)

匿名类型投影是不可能的,因为除了dynamicobjectIQueryable之类的非泛型类型之外,无法定义类型化结果,但是你会有问题消耗它。

但是,可以将投影重用于自定义类型(例如样本TestClass)。但是不是构造函数,而是必须将代码放在表达式返回方法中。

例如,而不是这个

public TestClass(IGrouping<int, ItemResponse> values)
{
    ItemID = values.Key;
    Average = values.Average(g => g.OptionValue);
    // ...etc. lots of properties
} 

你可以使用这样的东西

static Expression<Func<IGrouping<int, ItemResponse>, TestClass>> ToTestClass()
{
    return values => new TestClass
    {
        ItemID = values.Key,
        Average = values.Average(g => g.OptionValue)
        // ...etc. lots of properties
    };
}

,示例查询将是

var result = ItemResponses
    .GroupBy(ir => ir.ItemID)
    .Select(ToTestClass());