Получение суммы столбца на основе имени столбца - PullRequest
0 голосов
/ 01 сентября 2011

Мне нужно получить сумму столбцов на основе названия столбца. В настоящее время я использую блок 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 ]

2 голосов
/ 01 сентября 2011

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);
    }
}
0 голосов
/ 01 сентября 2011

Без отражения вы не можете ссылаться на имя свойства по строковому значению. И отражение было бы плохим выбором здесь. Я бы порекомендовал создать в классе свойство, содержащее ваши итоги, которое выполняет следующие действия:

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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...