0

我有一堂课Product

class Product
{ 
   int Id { get; set; }
   string Name { get; set; }
   int CategoryId { get; set; }
   int PlantId { get; set; }
   DateTime ProductionDate { get; set; }
}

我想LINQ GroupBy在多个属性上使用,但我事先不知道有多少以及哪些属性。例如,我可能想按 just CategoryId、 justPlantId或 both 分组。我在网上找到了一篇文章,描述了如何动态地使用 LINQ GrouBy

这可能确实有效,但如果我想在不知道粒度的情况下ProductionDate.Year执行Group By?ProductionDate.Month作为粒度,我的意思是我是想对Products特定年份的所有产品进行分组,还是将组缩小到月份。

我找到的唯一合乎逻辑的解决方案是:

public ProductInfo GetGroupedProducts(int? year, int? month, int? selectedCategoryId, int? selectedPlantId)
{
List<Product> products = GetProducts();

var groupedProducts = products.GroupBy(p => new { (year == null ? p.ProductionDate.Year : string.Empty),
                                                  (month == null ? p.ProductionDate.Month : string.Empty),
                                                  (selectedCategoryId == null ? p.CategoryId : string.Empty),
                                                  (selectedPlantId == null ? p.PlantId : string.Empty)
});

//perform some additional filtering and assignments 

}

但我想可能会有一个更清洁、更合适的解决方案。使用基于字符串的旧式查询构建方式,这项任务更容易完成。如果没有其他办法,我真的认为这是LINQ需要改进的一部分。

4

2 回答 2

0

如果我明白你在问什么,我有一个类似的问题Reversing typeof to use Linq Field<T>

我会做类似的事情

public static IEnumerable<IGrouping<string, TElement>> GroupMany<TElement>(
    this IEnumerable<TElement> elements, 
    params Func<TElement, object>[] groupSelectors)
    {
        return elements.GroupBy(e => string.Join(":", groupSelectors.Select(s => s(e))));
    }

然后你可以调用你的函数

var groupedProducts = products.GroupMany(p => p.CategoryId , p => p.ProductionDate.Month);

函数通过用冒号分隔的属性字符串进行分组。我这样做的原因是因为字符串的哈希码保证与类相同。

于 2012-12-04T08:30:21.597 回答
0

更清洁的解决方案是使用这种扩展方法:

public static TResult With<TInput, TResult>(this TInput? o, Func<TInput, TResult>
    selector, TResult defaultResult = default(TResult)) where TInput : struct
{
    return o.HasValue ? selector(o.Value) : defaultResult;
}

像这样:

string result = year.With(T => p.ProductionDate.Year, string.Empty);

其中,如果空值没问题:

string result = year.With(T => p.ProductionDate.Year);

或具有T价值int的东西int?


但是,您知道,更好的解决方案已经存在,所以请随意扩展您的代码,以便我对其进行分析。

于 2012-12-03T11:57:07.747 回答