как избежать этого дубликата кода с помощью делегатов / лямбда-выражений - PullRequest
2 голосов
/ 31 декабря 2010

у меня есть этот код ниже, который перебирает структуру данных, образует словарь.

У меня этот код дублируется несколько раз, единственное отличие состоит в том, что ключ к словарю

ниже приведен код:

  task.Project + task.Name

, который является ключом к словарю, но в других случаях его просто:

 task.Project

или просто

 task.Name

Вот пример одного из жестко закодированных методов «Bucket».

Моя цель - использовать универсальный метод «Bucket», в котором я мог бы иметь обратный вызов или какой-то способ передать функцию для вычисленияключ.

Как лучше всего это сделать?

private Dictionary<string, TeamHours> BucketByProjectTask(Dictionary<string, TimeBooking> timebookings)
{
    Dictionary<string, TeamHours> dict = new Dictionary<string, TeamHours>();

    foreach (var name in timebookings.Keys)
    {
        TimeBooking tb = timebookings[name];
        Person p = tb.Person;

        foreach (var booking in tb.WeeklyTimeBookings.Keys)
        {
            var item = tb.WeeklyTimeBookings[booking];
            foreach (var task in item.TaskSlices)
            {
                if (dict.ContainsKey(task.Project + task.Name))
                {
                    TeamHours th = dict[task.Project + task.Name];
                    th.Hours = th.Hours + task.Hours;
                }
                else
                {
                    TeamHours th = new TeamHours();
                    th.Hours = task.Hours;
                    th.Project = task.Project;
                    th.Task = task.Name;
                    th.Workstream = tb.Person.OrganisationalUnitName;
                    dict[task.Project + task.Name] = th;
                }
            }

        }

    }
    return dict;
}

1 Ответ

2 голосов
/ 31 декабря 2010

Ну, вы в основном ответили на вопрос сами.Либо передайте делегат в метод, либо унаследуйте разные реализации, и специализируйте, реализуя абстрактный метод.Другим вариантом является разделение алгоритма построения ключа как интерфейса, что приводит к лучшему разделению задач, но для простых сценариев издержки могут быть слишком большими.

Вариант 1 - делегаты

private Dictionary<string, TeamHours> BucketByProjectTask(Dictionary<string, TimeBooking> timebookings, Func<string, Task> getTaskKey)
{
    …
    dict[getTaskKey(task)] = th;
    …
}

Подходит для использования в сильно локализованных сценариях (т. Е. Реализации и использовании private для одного класса) с помощью всего нескольких простых выражений построения ключей.

Вариант 2 - абстрактный класс и метод

class abstract BucketAlgorithm
{
    protected abstract string GetTaskKey(Task task);


    public  Dictionary<string, TeamHours> BucketByProjectTask(Dictionary<string, TimeBooking> timebookings)
    {
        …
        dict[GetTaskKey(task)] = th;
        …
    }
}

class SpecificBucketAlgorithm : BucketAlgorithm
{
    protected override string GetTaskKey(Task task) { … }
}

Подходит для использования в средней области, например, в одной сборке, где нет необходимости в лучшем разделении задач (интерфейсы и реализация) или когда требуется несколько нетривиальных алгоритмов построения ключей.

Вариант 3- разложен на интерфейс

interface ITaskKeyGenerator
{
    string GetTaskKey(Task task);
}

class BucketAlgorithm
{
    public BucketAlgorithm(ITaskKeyGenerator taskKeyGenerator)
    {
        this.taskKeyGenerator = taskKeyGenerator;
    }

    private ITaskKeyGenerator taskKeyGenerator;

    public  Dictionary<string, TeamHours> BucketByProjectTask(Dictionary<string, TimeBooking> timebookings)
    {
        …
        dict[taskKeyGenerator.GetTaskKey(task)] = th;
        …
    }
}

Подходит для сценариев, где требуется тщательное разделение задач или когда могут существовать несколько сложных алгоритмов построения ключей или даже они могут быть предоставлены извне пользователями API.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...