汇总集合的所有属性,并将其动态分配给另一个对象 [英] Sum up all the properties of a collection and dynamically assigned it to another object

查看:92
本文介绍了汇总集合的所有属性,并将其动态分配给另一个对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在类型为DataResponselst中有一个对象集合,我想做的就是总结该集合的所有intdecimal属性,并分配每个属性的结果到另一个对象DataContainerResponse,该对象具有与要累加的属性名称和类型完全相同的属性名称(和类型).

I have a collection of object in lst of type DataResponse and what I would like to do is sum up all the properties that are int and decimal of this collection and assign the result of each property to another object DataContainerResponse that has the same exact property names(and types) as the those that are being summed up.

我可以通过手动键入每个属性并执行.Sum(s=>s.<propertyname>来手动执行此操作.但是那是90年代.下面是我徒劳无功的尝试.坦白说,我以前从未将var分配给lambda表达式,我什至不知道是否有可能.Sum(s=><var name>);

I can do this manually by typing out each property by hand and do a .Sum(s=>s.<propertyname>. But that so 90s. Below is my fruitless attempt to juice it out. Frankly, I never assigned a var to a lambda expression before and I don't even know if it's possible .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]));

        }
    }

推荐答案

如果想全面思考,可以尝试以下类似方法.我没有优化代码,却以最快的速度完成了代码.因此,对于凌乱的外观和Im感到抱歉,假设属性名称在要聚合的聚合结果类和单元类中相同.

If you want to go with full reflection, you can try something like the following. I didnt optimize the code, did it as fast as I can. So sorry for the messy look and Im assuming the property names are same in the aggregated result class and the unit class that you are aggregating against.

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可以像以下那样进行基准测试.

But, as a suggestion, if you want to go with this approach, its better if you can cache all the reflection invokes you're making as they are costly. And the 90's approach would still win in benchmark. Like the example above would benchmark like the following with the simple StopWatch.

1.8193
0.4476
Press any key to continue . . .

第一个是DoAggregationReflection的执行时间,最后一个是DoAggregation的执行时间.您可以根据需要尽可能多地优化反射,但是我认为它仍然无法与基本反射竞争.

The first one is the execution time of DoAggregationReflection and the last one is the execution time of DoAggregation. You can optimize the reflection one as much as you want but I think it would still fail to compete with the basic one.

有时候90年代更好. ;)尽管您仍然会使用LINQ进行实际的求和,所以不再是90了,因为根据

Sometime's the 90's are way better. ;) Although you'd still use LINQ to do the actual summation so that's not that 90's anymore as LINQ was born in 2007 according to wikipedia.

这篇关于汇总集合的所有属性,并将其动态分配给另一个对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆