Статический словарь, содержащий делегаты для методов экземпляра - PullRequest
7 голосов
/ 12 августа 2011

У меня есть этот метод с огромным оператором switch, подобным следующему:

public bool ExecuteCommand(string command, string args)
{
    bool result = false;
    switch (command)
    {
        case "command1": result = Method1(args); break;
        case "command2": result = Method2(args); break;
        // etc.
    }
    return result;
}
private bool Method1(string args) {...}

Теперь я подумал о замене этого словаря из Func<> делегатов, чтобы я мог исключить оператор switch:

private Dictionary<string, Func<string, bool>> _commands = new ...;
public MyClass()
{
    _commands.Add("command1", Method1);
    // etc:
}
public bool ExecuteCommand(string command, string args)
{
    return _commands[command](args);
}

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

Возможно ли как-то создать этот словарь (содержащий делегаты для методов экземпляра)статический член, который будет инициализирован только один раз, в статическом конструкторе?

Например, что-то вроде этого (не работает):

private static Dictionary<string, Func<string, bool>> _commands = new ...;
static MyClass()
{
    // the following line will result in a compiler error:
    // error CS0120: An object reference is required for the non-static field,
    // method, or property 'MyClass.Method1(string, string)'
    _commands.Add("command1", MyClass.Method1);
}

1 Ответ

19 голосов
/ 12 августа 2011

Вы можете инициализировать его в статическом конструкторе - но вам нужно будет создать экземпляры MyClass, что может быть не тем, что вы хотите, потому что я предполагаю, что вы хотите, чтобы команда выполнялась "вконтекст "экземпляра, к которому был вызван Execute.

В качестве альтернативы, вы можете заполнить словарь делегатами, которые также принимают экземпляр MyClass, например так:

class MyClass
{
    static Dictionary<string, Func<MyClass, string, bool>> commands
        = new Dictionary<string, Func<MyClass, string, bool>>
    {
        { "Foo", (@this, x) => @this.Foo(x) },
        { "Bar", (@this, y) => @this.Bar(y) }
    };

    public bool Execute(string command, string value)
    {
        return commands[command](this, value);
    }

    public bool Foo(string x)
    {
        return x.Length > 3;
    }

    public bool Bar(string x)
    {
        return x == "";
    }
}

Теоретически я считаю, что это можно сделать без лямбда-выражения, создав «открытый делегат», но для этого потребуется немного больше работы с использованием отражения.Если вы не возражаете против уродства и крошечного снижения производительности из-за дополнительной косвенности, я думаю, что этот подход должен работать довольно хорошо.

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