Переменное количество параметров - PullRequest
1 голос
/ 18 ноября 2011

Я улучшаю существующую систему обмена сообщениями для моего проекта, которая должна принимать переменное количество параметров. Прямо сейчас дженерики используются для передачи аргументов в систему. Много кода повторяется, поэтому возникает вопрос - возможно ли объединить все версии класса, которые принимают разное количество параметров, в один класс? Всю систему сообщений, которую я беру за основу, можно найти здесь: CSharpMessenger

выдержки из кода:

public delegate void Callback();
public delegate void Callback<T>(T arg1);
public delegate void Callback<T, U>(T arg1, U arg2);

Версия без параметров:

static public class Messenger
{
    private static Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();

    static public void AddListener(string eventType, Callback handler)
    {
        if (!eventTable.ContainsKey(eventType))
        {
            eventTable.Add(eventType, null);
        }
        // Add the handler to the event.
        eventTable[eventType] = (Callback)eventTable[eventType] + handler;
    }

    static public void Invoke(string eventType)
    {
        Delegate d;
        if (eventTable.TryGetValue(eventType, out d))
        {
            Callback callback = (Callback) d;
            if (callback != null)
            {
                callback();
            }
        }
    }
}

Версия с одним параметром:

static public class Messenger<T>
{
    private static Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();

    static public void AddListener(string eventType, Callback<T> handler)
    {
        if (!eventTable.ContainsKey(eventType))
        {
            eventTable.Add(eventType, null);
        }
        // Add the handler to the event.
        eventTable[eventType] = (Callback<T>)eventTable[eventType] + handler;
    }

    static public void Invoke(string eventType, T arg1)
    {
        Delegate d;
        if (eventTable.TryGetValue(eventType, out d))
        {
            Callback<T> callback = (Callback<T>) d;
            if (callback != null)
            {
                callback(arg1);
            }
        }
    }
}

Версия с двумя параметрами:

static public class Messenger<T, U>
{
    private static Dictionary<string, Delegate> eventTable = new Dictionary<string, Delegate>();

    static public void AddListener(string eventType, Callback<T, U> handler)
    {
        if (!eventTable.ContainsKey(eventType))
        {
            eventTable.Add(eventType, null);
        }
        // Add the handler to the event.
        eventTable[eventType] = (Callback<T, U>)eventTable[eventType] + handler;
    }

    static public void Invoke(string eventType, T arg1, U arg2)
    {
        Delegate d;
        if (eventTable.TryGetValue(eventType, out d))
        {
            Callback<T, U> callback = (Callback<T, U>) d;
            if (callback != null)
            {
                callback(arg1, arg2);
            }
        }
    }
}

Как вы можете видеть, большая часть кода повторяется, возможно ли создать какую-то общую версию одного и того же класса, которая будет принимать переменное число параметров и избежать повторения одного и того же кода столько раз?

Спасибо.

1 Ответ

2 голосов
/ 18 ноября 2011

Параметры обратного вызова обычно передаются в подкласс EventArgs.Уже есть простой обобщенный делегат, который абстрагирует это: EventHandler<TEventArgs> where TEventArgs : EventArgs.Изменчивость параметров может быть добавлена ​​к подклассам EventArgs.

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

public static class Messenger<TEventArgs> where TEventArgs : EventArgs {
  private static Dictionary<string, EventHandler<TEventArgs>> eventTable = 
    new Dictionary<string, EventHandler<TEventArgs>>();

  public static void AddListener(string eventType, EventHandler<TEventArgs> handler) {
    if (eventTable.ContainsKey(eventType)) {
      eventTable[eventType] = eventTable[eventType] + handler;
    }
    else {
      eventTable.Add(eventType, handler);
    }
  }

  public static void Invoke(string eventType, TEventArgs args) {
    EventHandler<TEventArgs> d;
    if (eventTable.TryGetValue(eventType, out d)) {
      if (d != null) {
        d(args);
      }
    }
  }
}
...