有没有办法概括行动和行动<t>?

时间:2016-05-27 11:55:37

标签: c# generics action extension-methods

所以我有一个扩展方法,允许我在执行操作时记录某些内容。实现如下:

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

    });
}

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

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

3 个答案:

答案 0 :(得分:3)

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

鉴于您现有的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);
}

答案 1 :(得分:2)

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

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

答案 2 :(得分:2)

您可以使用类型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