在C#中确定对象o是否是动作< ...>或者Func< ....>

时间:2011-10-21 22:24:38

标签: c# reflection metaprogramming

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

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

是否有一种通用方法可以发现给定的密钥k指向Action或Func,然后调用相同的值?

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

我考虑过使用动态关键字,只是在生成的对象上调用Invoke(args),但这似乎很慢而且不够优雅。

2 个答案:

答案 0 :(得分:4)

你可以测试它是代表:

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

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

答案 1 :(得分:2)

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

首先,将字典设为字典&lt; whatever,Delegate&gt;而不是反对。

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

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

不难想象将其构建为一个小型库并重新使用它。