根据列名获取列的总和

时间:2011-08-31 22:38:21

标签: c# entity-framework linq-to-sql c#-4.0

我需要根据列的名称获取列的总和。目前,我正在使用IF ELSE块来处理它,但我希望有更自动的方法来完成这类工作。

什么有效:

foreach (var day in bydates)
            {
                var bymile_bydate = bymile.Where(x => x.Date == day).ToList();

                foreach (var r in results)
                {
                    var name = r.name;
                    if (name.Equals("TotalIssues"))
                    {
                        r.data.Add(bymile_bydate.Sum(x => x.TotalIssues).Value);
                    }
                    else if (name.Equals("TotalCritical"))
                    {
                        r.data.Add(bymile_bydate.Sum(x => x.TotalCritical).Value);
                    }
                }
            }

我希望如何让它发挥作用:

        foreach (var day in bydates)
        {
            var bymile_bydate = bymile.Where(x => x.Date == day).ToList();

            foreach (var r in results)
            {
                r.data.Add(bymile_bydate.Sum(x=> x.(r.name)).Value);
            }
        }

那么无论如何这样做?

2 个答案:

答案 0 :(得分:2)

对于访问在编译时名称未知的成员,C#没有很好的支持。在这种情况下我经常做的是给代表返回属性的名称字典:

// assuming your objects are of type ClassX and your properties are decimals
static Dictionary<string, Func<ClassX, decimal>> PropertyLookup = 
    new Dictionary<string, Func<ClassX, decimal>>
    { { "TotalIssues", x => x.TotalIssues },
      { "TotalCritical", x => x.TotalCritical },
    };

foreach (var day in bydates)
{
    var bymile_bydate = bymile.Where(x => x.Date == day).ToList();

    foreach (var r in results)
    {
        var name = r.name;
        r.data.Add(bymile_bydate.Sum(PropertyLookup[name]).Value);
    }
}

如果您不想提前定义属性名称,可以使用反射来获取代理。这是一个实现,它将代理缓存在字典中,就像之前的解决方案一样:

// assuming your objects are of type ClassX and your properties are decimals
static Dictionary<string, Func<ClassX, decimal>> PropertyLookup = 
    new Dictionary<string, Func<ClassX, decimal>>();

foreach (var day in bydates)
{
    var bymile_bydate = bymile.Where(x => x.Date == day).ToList();

    foreach (var r in results)
    {
        var name = r.name;
        if (!PropertyLookup.ContainsKey(name))
            PropertyLookup[name] = (Func<ClassX, decimal>)Delegate.CreateDelegate(
                typeof(Func<ClassX, decimal>),
                typeof(ClassX).GetProperty(name).GetGetMethod());
        r.data.Add(bymile_bydate.Sum(PropertyLookup[name]).Value);
    }
}

答案 1 :(得分:0)

如果没有反射,则无法通过字符串值引用属性名称。反思在这里是一个糟糕的选择。我建议在类中创建一个包含以下内容的属性:

public int? RelevantTotal
{
    get
    {
        switch (this.name)
        {
            case "TotalIssues":
                return this.TotalIssues;
            case "TotalCritical":
                return this.TotalCritical;
            default:
                return 0;
        }
    }
}

当您遍历结果时,请调用该属性:

foreach (var day in bydates)
{
    var bymile_bydate = bymile.Where(x => x.Date == day).ToList();

    foreach (var r in results)
    {
        r.data.Add(bymile_bydate.Sum(x => r.RelevantTotal).Value);
    }
}