В C # определение, является ли объект o Action <...> или Func <....> - PullRequest
1 голос
/ 22 октября 2011

Скажем, у вас есть словарь <строка, объект>.Он может содержать десятичные дроби, строки или другие допустимые типы.Он также может содержать действия и функции, такие как:

Action<string> or Action<int,int,string> etc.

Существует ли общий способ обнаружить, что данный ключ k указывает на действие или функцию, а затем вызвать то же значение?

var value = dict[key];
//some sort of predicate checking if value is invokeable

Я рассмотрел использование динамического ключевого слова и простого вызова Invoke (args) для результирующего объекта, но это кажется медленным и не элегантным.

Ответы [ 2 ]

4 голосов
/ 22 октября 2011

Вы можете проверить это делегатом:

Delegate d = value as Delegate;
if(d != null) d.DynamicInvoke(args);

Однако!Знать, какие аргументы нужно предоставить (в массиве объектов), сложно, если вы не знаете сигнатуру перед вызовом.

2 голосов
/ 22 октября 2011

Если вы не хотите вызывать его динамически через динамический или Delegate.DynamicInvoke, вы можете использовать несколько общих методов расширения для выполнения теста за вас.

Сначала сделайте ваш словарь словарёмвместо объекта.

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

public static bool TryInvoke<T>(this Delegate del, T arg)
{
    var action = del as Action<T>;
    if (action != null)
    {
        action(arg);
        return true;
    }

    return false;
}

public static bool TryFunc<T, TResult>(this Delegate del, T arg, out TResult result)
{
    result = default(TResult);

    var func = del as Func<T, TResult>;
    if (func != null)
    {
        result = func(arg);
        return true;
    }

    return false;
}

Наконец, вы используете свои методы расширения следующим образом...

var value = dict[key];

if (value.TryInvoke(20))
{
    // do something...
}
else
{
    int result;
    if (value.TryInvoke(20, out result))
    {
        // do something else...
    }
}

Нетрудно представить, что можно создать небольшую библиотеку и использовать ее повторно.

...