我在 lst 中有一个对象集合类型 DataResponse我想做的是总结所有 int 的属性和 decimal这个集合的每个属性的结果分配给另一个对象 DataContainerResponse具有与正在汇总的属性名称(和类型)完全相同的属性名称(和类型)。
我可以通过手动输入每个属性并执行 .Sum(s=>s.<propertyname> 来手动执行此操作.但那是 90 年代。以下是我试图将其榨汁的无果而终的尝试。坦率地说,我以前从未将 var 分配给 lambda 表达式,我什至不知道这是否可能 .Sum(s=><var name>) ;
public DataAggragationResponse doAggregation(List<DataResponse> lst)
{
if (lst.Count == 0)
return null;
DataContainerResponse rd = new DataContainerResponse();
//If I do it manually typing each prop by hand.
rd.VIOL = lst.Sum(s => s.VIOL);
//Automation!!!
foreach (PropertyInfo propertyInfo in typeof(DataResponse).GetProperties())
{
rd.GetType().GetProperties().SetValue(lst.Sum(s => propertyInfo.Name[0]));
}
}
请您参考如下方法:
如果你想进行全反射,你可以试试下面的方法。我没有优化代码,而是尽可能快地完成了。对于凌乱的外观,我很抱歉,我假设聚合结果类和您要聚合的单元类中的属性名称相同。
class Program
{
static void Main(string[] args)
{
var list = new List<DataResponse>();
list.Add(new DataResponse() { Stuff = 1, Stuff2 = 2 });
list.Add(new DataResponse() { Stuff = 1, Stuff2 = 2 });
Stopwatch watch = new Stopwatch();
watch.Start();
var response = DoAggregationReflection(list);
watch.Stop();
Console.WriteLine(watch.Elapsed.TotalMilliseconds);
watch.Reset();
watch.Start();
var response2 = DoAggregation(list);
watch.Stop();
Console.WriteLine(watch.Elapsed.TotalMilliseconds);
}
public static DataAggragationResponse DoAggregationReflection(List<DataResponse> lst)
{
if (lst.Count == 0)
return null;
DataAggragationResponse aggrResponse = new DataAggragationResponse();
var responseType = typeof(DataResponse);
var aggrResponseType = typeof(DataAggragationResponse);
foreach (PropertyInfo propertyInfo in typeof(DataResponse).GetProperties())
{
aggrResponseType.GetProperty(propertyInfo.Name).SetValue(aggrResponse, lst.Sum(x => (int)responseType.GetProperty(propertyInfo.Name).GetValue(x)));
}
return aggrResponse;
}
public static DataAggragationResponse DoAggregation(List<DataResponse> lst)
{
if (lst.Count == 0)
return null;
DataAggragationResponse aggrResponse = new DataAggragationResponse();
aggrResponse.Stuff = lst.Sum(x => x.Stuff);
aggrResponse.Stuff2 = lst.Sum(x => x.Stuff2);
return aggrResponse;
}
}
public class DataResponse
{
public int Stuff { get; set; }
public int Stuff2 { get; set; }
}
public class DataAggragationResponse
{
public int Stuff { get; set; }
public int Stuff2 { get; set; }
}
但是,作为一个建议,如果您想采用这种方法,最好是可以缓存您正在进行的所有反射调用,因为它们的成本很高。 90 年代的方法仍然会在基准测试中获胜。就像上面的示例一样,使用简单的 StopWatch 进行如下基准测试。
1.8193
0.4476
Press any key to continue . . .
第一个是DoAggregationReflection的执行时间,最后一个是DoAggregation的执行时间。您可以根据需要优化反射,但我认为它仍然无法与基本反射竞争。
有时候 90 年代要好得多。 ;) 尽管您仍会使用 LINQ 进行实际求和,但根据 wikipedia,LINQ 诞生于 2007 年,因此这已不再是 90 年代了。 .
