0

我有以下代码,并试图避免代码重复 我想要做的是有一个自定义扩展方法,称为“SelectGrouped”

这将接受“Shift”对象,并返回匿名类型(不确定是否可能)

var groupedFillingsCurrentShift = currentShift.FilingMeasurements
                    .Where(f => TimeSpan.Parse(f.MeasurementTime.MeasurementTime) == ShiftEnd)
                    .GroupBy(f => new { f.Medium, f.MeasurementTime })
                    .Select(t => new { t.Key.Medium, t.Key.MeasurementTime, VolumeInTanks = t.Sum(s => s.Filing) })
                    .ToList();


if (previousShift != null)
{
    var groupedFillingsPreviousShift = previousShift.FilingMeasurements
        .Where(f => TimeSpan.Parse(f.MeasurementTime.MeasurementTime) == previousShift.ShiftEnd)
        .GroupBy(f => new { f.Medium, f.MeasurementTime })
        .Select(t => new { t.Key.Medium, t.Key.MeasurementTime, VolumeInTanks = t.Sum(s => s.Filing) })
        .ToList();

我想要实现的是让它看起来像这样

var groupedResultCurrentShift = 
   currentShift.SelectGrouped(t=>t.Medium, t.MeasurementTime, t.VolumenInTanks);

var groupedResultPreviousShift = 
   previousShift.SelectGrouped(t=>t.Medium, t.MeasurementTime, t.VolumenInTanks);
4

2 回答 2

2

不幸的是,你想要的不能以目前的形式完成。

首先,该变量t仅在 lambda 中具有值。逗号分隔参数,因此t失去了其他参数的范围。

其次,更重要的是,匿名类型根据定义是局部范围的,因为您必须使用“var”来暗示保存它们的变量的类型。您不能将它们作为参数传递,也不能将它们作为返回值返回(好吧,从技术上讲,您可以使用dynamic,但我们不要去那里,拜托)。

如果您要定义一个可用于保存最终形式的投影数据的命名类型,这将起作用:

internal class VolumeData
{
   public string Medium;
   public DateTime MeasurementTime;
   public decimal VolumeInTanks;
}

public static List<VolumeData> GetVolumeData(this Shift shift)
{
   return shift.FilingMeasurements
               .Where(f => TimeSpan.Parse(f.MeasurementTime.MeasurementTime) == ShiftEnd)
               .GroupBy(f => new { f.Medium, f.MeasurementTime })
               .Select(t => new VolumeData{ 
                                Medium = t.Key.Medium, 
                                MeasurementTime = t.Key.MeasurementTime, 
                                VolumeInTanks = t.Sum(s => s.Filing) })
               .ToList();
}

...

var groupedFillingsCurrentShift = currentShift.GetVolumeData();


if (previousShift != null)
    var groupedFillingsPreviousShift = previousShift.GetVolumeData();
于 2012-08-17T20:32:39.983 回答
0
var groupedResultCurrentShift = 
 currentShift.SelectGrouped(t=>t.Medium, t.MeasurementTime, t.VolumenInTanks);

没有意义,因为t第二个和第三个子句的 the 没有定义,并且VolumenInTanks与您尚未创建的属性相关。

我们还有一个问题,因为Select您的查询中的 与之前在同一范围内定义的匿名对象有关。这阻止了我们定义一个方法,让我们传入一个定义应该选择什么的 lambda。

然而:

currentShift.FilingMeasurements
                .Where(f => TimeSpan.Parse(f.MeasurementTime.MeasurementTime) == ShiftEnd)
                .GroupBy(f => new { f.Medium, f.MeasurementTime })
                .Select(t => new { t.Key.Medium, t.Key.MeasurementTime, VolumeInTanks = t.Sum(s => s.Filing) })
                .ToList();

相当于;

currentShift.FilingMeasurements
                .Where(f => TimeSpan.Parse(f.MeasurementTime.MeasurementTime) == ShiftEnd)
                .GroupBy(f => new { f.Medium, f.MeasurementTime }, s => s.Filing)
                .Select(t => new { t.Key.Medium, t.Key.MeasurementTime, VolumeInTanks = t.Sum() })
                .ToList();

现在,这还不完全存在,但让我们考虑一下,我们从以下位置获得了相同的信息:

currentShift.FilingMeasurements
                .Where(f => TimeSpan.Parse(f.MeasurementTime.MeasurementTime) == ShiftEnd)
                .GroupBy(f => new { f.Medium, f.MeasurementTime }, s => s.Filing)
                .Select(t => new { t.Key, VolumeInTanks = t.Sum() })
                .ToList();

所以。如果您愿意做item.Key.Medium而不是item.Medium,那么我们在做生意:

我们需要一个返回类型,所以我们将创建一个:

public class GroupedCount<T>
{
  public<T> Key{get;set;}
  public int Count{get;set;}//bit more of a general-purpose name than VolumeInTanks
}

现在,创建我们的方法:

public static List<GroupedCount<TKey>> ToGroupedCounts<TSource, TKey>(this IQueryable<TSource> source, Func<TSource, bool> pred, Func<TSource, TKey> keyGen, Func<TSource, int> tallyGen)
{
    currentShift.FilingMeasurements
                .Where(pred)
                .GroupBy(keyGen, tallyGen)
                .Select(t => new GroupedCount<TKey>{ Key = t.Key, Count = t.Sum() })
                .ToList();
}

我们现在可以调用:

currentShift.ToGroupedCounts(
  f => TimeSpan.Parse(f.MeasurementTime.MeasurementTime) == ShiftEnd,
  f => new { f.Medium, f.MeasurementTime },
  s => s.Filing
);

由于我们希望这是通用ToList()的,除非在特定情况下确实需要它,否则不应调用它,因此返回 IQueryable 更有意义:

public static IQueryable<GroupedCount<TKey>> ToGroupedCounts<TSource, TKey>(this IQueryable<TSource> source, Func<TSource, bool> pred, Func<TSource, TKey> keyGen, Func<TSource, int> tallyGen)
{
    currentShift.FilingMeasurements
                .Where(pred)
                .GroupBy(keyGen, tallyGen)
                .Select(t => new GroupedCount<TKey>{ Key = t.Key, Count = t.Sum() });
}
于 2012-08-17T20:54:19.197 回答