C# 汇总集合的所有属性并将其动态分配给另一个对象

C# 汇总集合的所有属性并将其动态分配给另一个对象,c#,linq,reflection,lambda,C#,Linq,Reflection,Lambda,我在lst中有一个DataResponse类型的对象集合,我要做的是汇总该集合的所有int和decimal属性,并将每个属性的结果分配给另一个对象DataContainerResponse,该对象与要汇总的对象具有相同的属性名称和类型 我可以手动键入每个属性,然后执行.Sums=>s。。但那是90年代。下面是我徒劳的尝试榨汁出来。坦白地说,我以前从未给lambda表达式赋值过var,我甚至不知道这是否可能 希望这能帮助你。我希望我能保留与我刚才提出的问题的SO链接。对不起,原来的海报没有提到他/

我在lst中有一个DataResponse类型的对象集合,我要做的是汇总该集合的所有int和decimal属性,并将每个属性的结果分配给另一个对象DataContainerResponse,该对象与要汇总的对象具有相同的属性名称和类型

我可以手动键入每个属性,然后执行.Sums=>s。。但那是90年代。下面是我徒劳的尝试榨汁出来。坦白地说,我以前从未给lambda表达式赋值过var,我甚至不知道这是否可能


希望这能帮助你。我希望我能保留与我刚才提出的问题的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年代的小伙子不管怎样,我很乐意帮助巴德。