【问题标题】:Create a method like Action.Invoke创建一个类似 Action.Invoke 的方法
【发布时间】:2021-02-25 19:16:03
【问题描述】:

我正在尝试编写一个简单的方法来使代码更具可读性。我正在写一个我有异步任务的部分,所以我使用 Action 作为我的方法的参数,以便在方法完成时获得回调。

简而言之,我的签名总是这样:

public void myAsyncMethod(...params..., Action<other params> onFinish = null)

我使用默认的 Action 作为 null 只是为了给库用户更多的灵活性,但在我的实现中我总是编写这段代码:

if (onFinish != null)
{
    UnityMainThreadDispatcher.Instance().Enqueue(
        () => onFinish(other params)
    );
}

这是因为统一我提供了在主线程上启动动作的可能性,以防用户需要与图形循环交互。 我的想法是:我可以把那段代码放在一个方法中,让方法实现更具可读性吗? 以这样的方式调用那个东西真的很棒:

onFinish?.InvokeOnMainThread(other params);

有点像Action?.Invoke 方式。 因此,我在 c# 中对扩展方法、操作和泛型进行了一些搜索,但我无法掌握使用泛型构建方法来完成我想要达到的目标。 我真的不知道要搜索什么才能达到我的目标,我环顾四周,但可能我还不够好,无法将这些概念放在一起达到我的目标。

到目前为止,我认为这样的事情(不起作用):

public static void InvokeOnMainThread(this Action<T1, T2>, T1 t1, T2 t2){ ... }
public static void InvokeOnMainThread<Action, T1, T2>(Action<T1, T2>, T1 t1, T2 t2){ ... }

我使用带有 2 个参数的 Action 只是因为在我的情况下是最常见的,但我需要带有 0 到 4 个参数的相同调用(但我认为当我能够掌握这个概念时,它会很容易扩展或至少我可以复制它以获得我需要的参数数量)。

【问题讨论】:

标签: c# extension-methods


【解决方案1】:

您需要为 0-4 个可能的参数创建单独的扩展方法,如下所示:

public static partial class UnityExtensions
{
    public static void InvokeOnMainThread(this Action onFinish)
    {
        if (onFinish != null) // Or throw ArgumentNullException() if you prefer
            UnityMainThreadDispatcher.Instance().Enqueue(() => onFinish());
    }
    
    public static void InvokeOnMainThread<T1>(this Action<T1> onFinish, T1 t1)
    {
        if (onFinish != null)
            UnityMainThreadDispatcher.Instance().Enqueue(() => onFinish(t1));
    }
    
    public static void InvokeOnMainThread<T1, T2>(this Action<T1, T2> onFinish, T1 t1, T2 t2)
    {
        if (onFinish != null)
            UnityMainThreadDispatcher.Instance().Enqueue(() => onFinish(t1, t2));
    }
    
    public static void InvokeOnMainThread<T1, T2, T3>(this Action<T1, T2, T3> onFinish, T1 t1, T2 t2, T3 t3)
    {
        if (onFinish != null)
            UnityMainThreadDispatcher.Instance().Enqueue(() => onFinish(t1, t2, t3));
    }
    
    public static void InvokeOnMainThread<T1, T2, T3, T4>(this Action<T1, T2, T3, T4> onFinish, T1 t1, T2 t2, T3 t3, T4 t4)
    {
        if (onFinish != null)
            UnityMainThreadDispatcher.Instance().Enqueue(() => onFinish(t1, t2, t3, t4));
    }
}

然后你就可以做到:

onFinish?.InvokeOnMainThread(param1, param2); // Or however many parameters you have.

正如 Can I have a variable number of generic parameters? 中所述,c# 不允许使用可变数量的泛型参数。这就是为什么例如每个支持的参数数量都有不同的Tuple.Create&lt;&gt;() 方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-03
    • 2021-01-03
    • 1970-01-01
    • 2013-03-25
    相关资源
    最近更新 更多