在c#中,确定对象o是否为动作<…>或Func< . .祝辞

本文关键字:祝辞 Func 是否 对象 | 更新日期: 2023-09-27 18:11:55

假设你有一个字典<字符串,对象>。它可能包含小数、字符串或其他有效类型。它还可以包含Actions和Funcs,如:

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

是否有一种通用的方法来发现一个给定的键k指向一个动作或函数,然后调用相同的值?

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

我考虑过使用动态关键字并对结果对象简单地调用Invoke(args),但这似乎很慢而且不美观。

在c#中,确定对象o是否为动作<…>或Func< . .祝辞

你可以测试它是一个委托:

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

!如果您在调用之前不知道签名,那么要知道(在对象数组中)提供什么参数是很棘手的。

如果您不想通过动态或委托动态调用它。DynamicInvoke,您可以使用一些通用的扩展方法来为您执行测试。

首先,将你的字典命名为Dictionary<whatever,>而不是object。

接下来,创建两个扩展方法(或更多,以匹配您所关心的委托类型)。

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...
    }
}

不难想象把它构建成一个小库并重新使用。