在 C# 中,确定对象 o 是否为 Action<...>或 Func<...>;

发布于 2024-12-11 16:46:59 字数 385 浏览 0 评论 0 原文

假设你有一本字典 <字符串,对象> 。它可能包含小数、字符串或其他有效类型。它还可以包含 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

我考虑过使用dynamic关键字并简单地在结果对象上调用Invoke(args),但这看起来很慢而且不优雅。

Say you have a Dictionary < string,object > . It might contain decimals, strings or other valid types. It could also contain Actions and Funcs like:

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

Is there a general way to discover that a given key k points to an Action or Func and then invoke that same value?

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

I have considered using the dynamic keyword and simply calling Invoke( args ) on the resulting object, but this seems slow and inelegant.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冷了相思 2024-12-18 16:46:59

你可以测试它是一个代表:

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

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

You could test off it is a delegate:

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

However! Knowing what args to provide (in an object-array) is tricky if you don't know the signature ahead of the invoke.

爱你不解释 2024-12-18 16:46:59

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

首先,将你的字典设置为 Dictionary而不是对象。

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

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

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

If you don't want to invoke it dynamically via dynamic, or Delegate.DynamicInvoke, you could use some generic extension methods to perform the test for you.

First, make your dictionary a Dictionary<whatever, Delegate> rather than object.

Next, create a couple of extension methods (or more to match the delegate types you care about).

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

Finally, you use your extension methods like so...

var value = dict[key];

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

It's not hard to imagine building this up as a small library and re-using it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文