有没有办法泛化Action和Action<T>?

Is there a way to generalise Action and Action<T>?

所以我有一个扩展方法,允许我在执行操作时记录一些东西。实现是这样的:

public static Action Log(this Action action, string log) {
    return (() => {
        Console.WriteLine(log);
        action();

    });
}

但我想允许动作也是 Action<T>。有没有办法概括这一点,以便 log 被记录下来,但它不会更改操作的签名?

或者我需要 2 种方法,一种用于 Action,一种用于 Action<T>

您将需要两种方法,因为 ActionAction<T> 在这种情况下彼此不兼容。

如果 Action 实际上是 Action<void> 来启用此行为,那将很有用,但事实并非如此。

您可以使用类型 Delegate 并像这样为您的操作提供参数 param object[]

public static Action Log(this Delegate action, string log, params object[] args)
{
    return () =>
    {
        Console.WriteLine(log);
        action.DynamicInvoke(args);
    };
}

您可以像这样使用此扩展程序:

Action<int> testAction = i => Console.WriteLine($"Test: {i}");
testAction.Log("Logging", 42).Invoke();

这会产生以下输出:

Logging
Test: 42

您需要单独的方法,但您可以根据另一个来实现一个以减少代码重复:

鉴于您现有的 Log(Action action, string log),您可以添加:

public static Action<T> Log<T>(this Action<T> action, string log) {
    return t => Log(() => action(t), log);
}

或者反过来:

public static Action<T> Log(this Action<T> action, string log) {
    return t => {
        Console.WriteLine(log);
        action(t);
    });
}

public static Action Log(this Action action, string log) {
    return () => Log<object>(t => action(), log);
}