C# 用于返回分组结果的Linq扩展
我有以下代码,并试图避免代码重复 我想做的是有一个自定义的扩展方法,比如“SelectGrouped” 它将接受一个“Shift”对象,并返回匿名类型(不确定是否可能) 我想要达到的是让它看起来像这样C# 用于返回分组结果的Linq扩展,c#,.net,linq,C#,.net,Linq,我有以下代码,并试图避免代码重复 我想做的是有一个自定义的扩展方法,比如“SelectGrouped” 它将接受一个“Shift”对象,并返回匿名类型(不确定是否可能) 我想要达到的是让它看起来像这样 var groupedResultCurrentShift = currentShift.SelectGrouped(t=>t.Medium, t.MeasurementTime, t.VolumenInTanks); var groupedResultPreviousShift
var groupedResultCurrentShift =
currentShift.SelectGrouped(t=>t.Medium, t.MeasurementTime, t.VolumenInTanks);
var groupedResultPreviousShift =
previousShift.SelectGrouped(t=>t.Medium, t.MeasurementTime, t.VolumenInTanks);
不幸的是,您想要的东西不能以当前的形式完成 首先,变量
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();
内部类卷数据
{
公共字符串媒体;
公共日期时间度量时间;
公共十进制卷索引;
}
公共静态列表GetVolumeData(此班次)
{
返回移位。归档测量
其中(f=>TimeSpan.Parse(f.MeasurementTime.MeasurementTime)==ShiftEnd)
.GroupBy(f=>new{f.Medium,f.MeasurementTime})
.Select(t=>newvolumedata{
中等=t.Key.Medium,
MeasurementTime=t.Key.MeasurementTime,
VolumeInTanks=t.Sum(s=>s.Filing)})
.ToList();
}
...
var groupedFillingsCurrentShift=currentShift.GetVolumeData();
if(上一个移位!=null)
var groupedFillingsPreviousShift=previousShift.GetVolumeData();
没有意义,因为第二个和第三个子句的t
没有定义,并且volumeInTanks
与您尚未创建的属性相关
我们还有一个问题,查询中的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
}
由于我们希望它是通用的,除非在特定情况下确实需要,否则不应调用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() });
}
public static IQueryable to groupedcounts(此IQueryable源、Func pred、Func keyGen、Func tallyGen)
{
电流移位。锉刀测量
.Where(pred)
.GroupBy(凯根、塔利根)
.Select(t=>newgroupedcount{Key=t.Key,Count=t.Sum()});
}
Thanx。这也是我的怀疑,我需要使用dynamic来实现这一点。(或硬键入一个类)。很好:)不太确定您对该键做了什么。这就是与计数一起出现的键类型,因此在调用的情况下,它是一个具有Medium
和MeasurementTime
属性的匿名对象。它是基于第二个参数创建的(第一个参数过滤掉那些你不想要的,第三个表示你要求和的属性)。
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
);
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() });
}