我发现我在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)只允许无参数构造函数和初始化器。所以这种方法似乎不起作用。
我是否有另一种方法可以简化这种类型的重复代码,只将它放在一个地方?
答案 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)
匿名类型投影是不可能的,因为除了dynamic
,object
或IQueryable
之类的非泛型类型之外,无法定义类型化结果,但是你会有问题消耗它。
但是,可以将投影重用于自定义类型(例如样本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());