简体   繁体   中英

How do I combine objects in a generic list into generic class?

So I have a generic list of objects, and I need to combine their properties to get list of sums.

public class PickupReport
{
    public int Units { get; set; }
    public int Revenue { get; set; }
    public int Accs { get; set; }
}

public class ReportBase<TReport>
{
    public List<TReport> Reports { get; set; }
    public List<int> Sum 
    {
        get
        {
            return new List<int>{1,2,3}
        }
    }
}

So, if I have

var reportBase = new ReportBase<PickupReport>();
reportBase.Reports = new List<PickupReport>{

new PickupReport{Units = 1, Revenue = 2, Accs = 3},
new PickupReport{Units = 4, Revenue = 5, Accs = 6},
new PickupReport{Units = 2, Revenue = 3, Accs = 4}

}

I need to get and calculate reportBase.Sum and it should be List<int> with {7, 10, 13}

Like {the sum of property #1 for all objects, the sum of property #2 for all objects, and so on.. }

Is it possible to do this somehow, given that the number of objects in the list is dynamic? Well, the number of object properties, too, but within the class.

@MongZhu only int

Then I would suggest to use reflection for this approach. Make it a method rather then a property:

public class ReportBase<TReport>
{

    public List<TReport> Reports { get; set; }

    public IEnumerable<int> CalculateSum()
    {
        foreach (var element in typeof(TReport).GetProperties())
        {
            if (element.PropertyType == typeof(int))
            {
                yield return Reports.Sum(x => (int)element.GetValue(x));
            }
        }
    }
}

Explanation:

This method iterates over all properties that are in the type and if it finds a property of type int it will calculate the sum of it from the entire list.

Here is a testprogramm and the result dump from LINQPad:

void Main()
{
    var reportBase = new ReportBase<PickupReport>();
    reportBase.Reports = new List<PickupReport>{

    new PickupReport(1,2,3),
    new PickupReport(4,5,6),
    new PickupReport(2,3,4)

    };

    reportBase.CalculateSum().Dump();
}

在此处输入图片说明

EDIT:

just noticed, that objects in my project can have two types of properties, not one

Here is a version where you can add types to a list of allowed sum up types:

public class ReportBase<TReport>
{
    public List<TReport> Reports { get; set; }

    List<Type> possibleTypes = new List<Type> {typeof(int), typeof(double)};

    public IEnumerable<double> CalculateSum()
    {
        foreach (PropertyInfo element in typeof(TReport).GetProperties())
        {
            if (possibleTypes.Contains(element.PropertyType))
            {
                yield return Reports.Sum(x => Convert.ToDouble(element.GetValue(x)));
            }
        }
    }
}

Now you can also handle double

This should get you a List<int> with the sums of all int properties of TReport :

var properties = typeof(PickupReport).GetProperties();
List<int> sum = new List<int>();
for (int i = 0; i<properties.Length; ++i)
{
    sum.Add(0);
    if (properties[i].PropertyType == typeof(int))
    {
        foreach (var report in reportBase.Reports)
        {
            sum[i] += (int) properties[i].GetValue(report);
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM