C# 汇总集合的所有属性并将其动态分配给另一个对象
我在lst中有一个DataResponse类型的对象集合,我要做的是汇总该集合的所有int和decimal属性,并将每个属性的结果分配给另一个对象DataContainerResponse,该对象与要汇总的对象具有相同的属性名称和类型 我可以手动键入每个属性,然后执行.Sums=>s。。但那是90年代。下面是我徒劳的尝试榨汁出来。坦白地说,我以前从未给lambda表达式赋值过var,我甚至不知道这是否可能C# 汇总集合的所有属性并将其动态分配给另一个对象,c#,linq,reflection,lambda,C#,Linq,Reflection,Lambda,我在lst中有一个DataResponse类型的对象集合,我要做的是汇总该集合的所有int和decimal属性,并将每个属性的结果分配给另一个对象DataContainerResponse,该对象与要汇总的对象具有相同的属性名称和类型 我可以手动键入每个属性,然后执行.Sums=>s。。但那是90年代。下面是我徒劳的尝试榨汁出来。坦白地说,我以前从未给lambda表达式赋值过var,我甚至不知道这是否可能 希望这能帮助你。我希望我能保留与我刚才提出的问题的SO链接。对不起,原来的海报没有提到他/
希望这能帮助你。我希望我能保留与我刚才提出的问题的SO链接。对不起,原来的海报没有提到他/她的名字
using System.Reflection;
public static Dictionary<string, string> GetPropertiesValue(object o)
{
Dictionary<string, string> PropertiesDictionaryToReturn = new Dictionary<string, string>();
foreach (MemberInfo itemMemberInfo in o.GetType().GetMembers())
{
if (itemMemberInfo.MemberType == MemberTypes.Property)
{
//object PropValue = GetPropertyValue(OPSOP, item.Name);
//string itemProperty = itemMemberInfo.Name;
//string itemPropertyValue = o.GetType().GetProperty(itemMemberInfo.Name).GetValue(o, null).ToString();
//Console.WriteLine(itemProperty + " : " + itemPropertyValue);
PropertiesDictionaryToReturn.Add(itemMemberInfo.Name, o.GetType().GetProperty(itemMemberInfo.Name).GetValue(o, null).ToString());
}
}
return PropertiesDictionaryToReturn;
}
这并不完全是你所需要的,但我认为你可以适应它。希望这能帮助你。我希望我能保留与我刚才提出的问题的SO链接。对不起,原来的海报没有提到他/她的名字
using System.Reflection;
public static Dictionary<string, string> GetPropertiesValue(object o)
{
Dictionary<string, string> PropertiesDictionaryToReturn = new Dictionary<string, string>();
foreach (MemberInfo itemMemberInfo in o.GetType().GetMembers())
{
if (itemMemberInfo.MemberType == MemberTypes.Property)
{
//object PropValue = GetPropertyValue(OPSOP, item.Name);
//string itemProperty = itemMemberInfo.Name;
//string itemPropertyValue = o.GetType().GetProperty(itemMemberInfo.Name).GetValue(o, null).ToString();
//Console.WriteLine(itemProperty + " : " + itemPropertyValue);
PropertiesDictionaryToReturn.Add(itemMemberInfo.Name, o.GetType().GetProperty(itemMemberInfo.Name).GetValue(o, null).ToString());
}
}
return PropertiesDictionaryToReturn;
}
这并不完全是您所需要的,但是,我认为您可以调整它。如果您想使用全反射,您可以尝试以下方法。我没有优化代码,而是尽可能快地完成了。所以很抱歉看起来很凌乱,我假设聚合结果类和聚合所针对的单元类中的属性名称相同
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; }
}
第一个是DoAggregationReflection的执行时间,最后一个是DoAggregation的执行时间。你可以优化反射一个尽可能多,但我认为它仍然无法与基本的竞争
90年代有时要好得多;虽然你仍然会使用LINQ来做实际的求和,所以根据数据,这已经不是90年代了,因为LINQ出生于2007年 如果您想使用全反射,可以尝试以下方法。我没有优化代码,而是尽可能快地完成了。所以很抱歉看起来很凌乱,我假设聚合结果类和聚合所针对的单元类中的属性名称相同
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; }
}
第一个是DoAggregationReflection的执行时间,最后一个是DoAggregation的执行时间。你可以优化反射一个尽可能多,但我认为它仍然无法与基本的竞争
90年代有时要好得多;虽然你仍然会使用LINQ来做实际的求和,所以根据数据,这已经不是90年代了,因为LINQ出生于2007年 我宁愿采取不同的方法。我将动态构建和编译一次,如下所示:
Func<DataContainerResponse, DataResponse, DataContainerResponse> aggregateFunc =
(result, item) =>
{
result.Prop1 += item.Prop1;
result.Prop2 += item.Prop2;
...
result.PropN += item.PropN;
return result;
}
而且用法很简单:
public DataContainerResponse DoAggregation(List<DataResponse> source)
{
return source.Aggregate(new DataContainerResponse(), AggregateFunc);
}
我宁愿采取不同的方法。我将动态构建和编译一次,如下所示:
Func<DataContainerResponse, DataResponse, DataContainerResponse> aggregateFunc =
(result, item) =>
{
result.Prop1 += item.Prop1;
result.Prop2 += item.Prop2;
...
result.PropN += item.PropN;
return result;
}
而且用法很简单:
public DataContainerResponse DoAggregation(List<DataResponse> source)
{
return source.Aggregate(new DataContainerResponse(), AggregateFunc);
}
您是否遇到过任何错误?这是您真实的用例吗?我的意思是,List@Sameed以下是错误CS0121。以下方法或属性之间的调用不明确:“Array.SetValueobject,params int[]”和“Array.SetValueobject,params long[]”@IvanStoev Yes sir。它尽可能真实。这会有什么不同呢?好吧,如果它是IQueryable,我会创建多个和选择器表达式。对于列表,我将构建简单的操作。您遇到过任何错误吗?这是您真实的用例吗?我的意思是,List@Sameed以下是错误CS0121。以下方法或属性之间的调用不明确:“Array.SetValueobject,params int[]”和“Array.SetValueobject,params long[]”@IvanStoev Yes sir。它尽可能真实。这会有什么不同呢?好吧,如果它是IQueryable,我会创建多个和选择器表达式。对于列表,我将创建简单的操作。谢谢@blaze_125。我当然可以把道具放在字典里,这样做。实际上,你不一定需要字典。字典方法对于我在其中使用该代码段的应用程序范围有效。不过,在您的情况下,您肯定可以在ForEach中做任何事情。我认为现在最适合您的是o.GetType.GetMembers、itemMemberInfo.Name和o.GetType.GetPropertyitemMemberInfo.Name.GetValueo、null.ToStringTanks@blaze_125中的每个MemberInfo itemMemberInfo片段的这些部分。我当然可以把道具放在字典里,这样做。实际上,你不一定需要字典。字典方法对于我在其中使用该代码段的应用程序范围有效。不过,在您的情况下,您肯定可以在ForEach中做任何事情。我认为现在最适合您的是o.GetType.GetMembers、itemMemberInfo.Name和o.GetType.GetPropertyitemMemberInfo.Name中的每个MemberInfo itemMemberInfo片段的这些部分,因为您的性能数字,您得到了奶酪。
我会用90年代的方式。这是一个用于移动应用程序的web服务,因此需要考虑速度。谢谢我不知道为什么我突然成了一个先生。我是90年代的孩子,不一定是90年代的小伙子不管怎样,我很乐意帮助巴德。先生,因为你的表现,你得到了奶酪。我会用90年代的方式。这是一个用于移动应用程序的web服务,因此需要考虑速度。谢谢我不知道为什么我突然成了一个先生。我是90年代的孩子,不一定是90年代的小伙子不管怎样,我很乐意帮助巴德。