Click here to Skip to main content
15,896,912 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi Friends,
I need to sum particular field of list of Objects. I have written a method with accepts Lists but don't know how to pass the field name.
For Example if i pass MarketValue it should return MarketValue Sum like wise if i pass Quantity it should return Quantity Sum

This is my class
C#
public class TopList
   {
        public static double marketsum = 1;
        public string Symbol{get;set;}
        public double MarketValue{get;set;}
        public double PreviousMarketVale{get;set;}
        public double Quantity{get;set;}
        public double MarketValuePercentage { get { return Math.Round((MarkrtValue / marketsum) * 100,2); } }
        public double ChangeInMarketValue {get { return Math.Round(((MarkrtValue-PreviousMarketVale)/MarkrtValue)*100,2);}}
   }


My Method
C#
public static double MarketSum(List<TopList>tl)//here it should accept one more paramter
        {
            return tl.Sum(s => s.MarketValue);//here i need to pass different fields
        }


This is how i invoke the method
C#
List<TopList> tl = new List<TopList>();
 double ms = MarketSum(tl);


Thanks in advance :)
Posted
Updated 28-Jul-15 10:24am
v4

I'd just abstract the field selection outside of the method:
C#
public static double MarketSum(List<TopList>tl, Func<TopList, double> accessor)
{
    return tl.Sum(accessor);
}

Calling it as:
C#
List<TopList> tl = new List<TopList>();
  double ms = MarketSum(tl, s => s.MarketValue);

Another option is to pre-define the accessor functions:
C#
private static Dictionary<string, Func<TopList, double>> Accessors = new Dictionary<string, Func<TopList, double>>() {
  { "MarketValue", s => s.MarketValue },
  { "Quantity", s => s.Quantity },
  // etc.
};
public static double MarketSum(List<TopList>tl, string accessorKey)
{
    Func<TopList, double>> accessor;
    if (!Accessors.TryGetValue(accessorKey, out accessor))
      throw new InvalidOperationException("No such accessor: " + accessorKey);
    return tl.Sum(accessor);
}

Calling it as:
C#
List<TopList> tl = new List<TopList>();
  double ms = MarketSum(tl, "MarketValue");

A third option is to use reflection to automatically pre-define the accessor functions:
C#
public static Dictionary<string, Func<TopList, double>> Accessors = GetPropertyAccessDictionary<TopList, double>();
static Dictionary<string, Func<Tclass, Tvalue>> GetPropertyAccessDictionary<Tclass, Tvalue>()
{
  Dictionary<string, Func<Tclass, Tvalue>> accessors = new Dictionary<string, Func<Tclass, Tvalue>>();
  PropertyInfo[] props = typeof(Tclass).GetProperties(BindingFlags.Public);
  Type valueType = typeof(Tvalue);
  foreach (var prop in props)
  {
    MethodInfo getter = prop.GetMethod;
    if (valueType.IsAssignableFrom(getter.ReturnType))
      accessors.Add(prop.Name, o => (Tvalue)(getter.Invoke(o, null)));
  }
  return accessors;
}

public static double MarketSum(List<TopList> tl, string accessorKey)
{
  Func<TopList, double> accessor = null;
  if (!Accessors.TryGetValue(accessorKey, out accessor))
    throw new InvalidOperationException("No such accessor: " + accessorKey);
  return tl.Sum(accessor);
}

Use it exactly the same as above.
The string-based lookup of the accessors is not a great architecture. It's OK if the strings are coming directly from user input. Even then, it's probably better to parse and validate that into something more structured.
 
Share this answer
 
v2
I would probably declare another class to contain your list and include the sum methods on that class.

C#
public class TopListItem
{
    public static double marketsum = 1;
    public string Symbol { get; set; }
    public double MarketValue { get; set; }
    public double PreviousMarketVale { get; set; }
    public double Quantity { get; set; }
    public double MarketValuePercentage { get { return Math.Round((MarketValue / marketsum) * 100, 2); } }
    public double ChangeInMarketValue { get { return Math.Round(((MarketValue - PreviousMarketVale) / MarketValue) * 100, 2); } }
}

public class TopList
{
    public static List<toplistitem> items { get; set; }

    static TopList()
    {
        items = new List<toplistitem>();
    }
    public double sumQuantity()
    {
        //Sum them here
        return 0;
    }
}


To invoke:
C#
TopList t1 = new TopList();
double totalQuantity = t1.sumQuantity();
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900