如何重构这个重复的LINQ代码?

Bre*_*ick 9 c# linq refactoring

我试图弄清楚如何很好地重构这个LINQ代码.此代码和其他类似代码在同一文件和其他文件中重复.有时被操纵的数据是相同的,有时数据会发生变化,逻辑也会保持不变.

以下是在不同对象的不同字段上运行的重复逻辑的示例.

public IEnumerable<FooDataItem> GetDataItemsByColor(IEnumerable<BarDto> dtos)
{
    double totalNumber = dtos.Where(x => x.Color != null).Sum(p => p.Number);
    return from stat in dtos
           where stat.Color != null
           group stat by stat.Color into gr
           orderby gr.Sum(p => p.Number) descending
           select new FooDataItem
           {
               Color = gr.Key,
               NumberTotal = gr.Sum(p => p.Number),
               NumberPercentage = gr.Sum(p => p.Number) / totalNumber
           };
}

public IEnumerable<FooDataItem> GetDataItemsByName(IEnumerable<BarDto> dtos)
{
    double totalData = dtos.Where(x => x.Name != null).Sum(v => v.Data);
    return from stat in dtos
           where stat.Name != null
           group stat by stat.Name into gr
           orderby gr.Sum(v => v.Data) descending
           select new FooDataItem
           {
               Name = gr.Key,
               DataTotal = gr.Sum(v => v.Data),
               DataPercentage = gr.Sum(v => v.Data) / totalData
           };
}
Run Code Online (Sandbox Code Playgroud)

任何人都有很好的重构方法吗?

mqp*_*mqp 11

像这样的东西:

public IEnumerable<FooDataItem> GetDataItems<T>(IEnumerable<BarDto> dtos,
    Func<BarDto, T> groupCriteria,
    Func<BarDto, double> dataSelector,
    Func<T, double, double, FooDataItem> resultFactory)
{
    var validDtos = dtos.Where(d => groupCriteria(d) != null);
    double totalNumber = validDtos.Sum(dataSelector);

    return validDtos
        .GroupBy(groupCriteria)
        .OrderBy(g => g.Sum(dataSelector))
        .Select(gr => resultFactory(gr.Key,
                                    gr.Sum(dataSelector),
                                    gr.Sum(dataSelector) / totalNumber));
}
Run Code Online (Sandbox Code Playgroud)

在您的示例中,您可以这样称呼它:

GetDataItems(
    x => x.Color,  // the grouping criterion
    x => x.Number, // the value criterion
    (key, total, pct) =>
        new FooDataItem {
            Color = key, NumberTotal = total, NumberPercentage = pct });
Run Code Online (Sandbox Code Playgroud)

如果您更改FooDataItem为更通用,那将更容易.

  • 尼斯.对于可读性,以避免重构现有的所有函数调用的,我可能还是换你来`GetDataItems`中的呼叫`GetDataItemsByColor(IEnumerable的<BarDto> DTOS)`函数. (2认同)