如何避免重复接受 Func<T, int> 作为参数的方法的多个重写

How to avoid repetition with multiple overrides of method accepting Func<T, int> as parameters

我想要一个 "generic" - 也就是说,如果可能的话,一个具有单一签名的方法 - 而不是下面的 copy/paste 代码。

我的目标是 "wrap" 来自第三方 DLL 的方法 Spy Double

    int spy(Func<int> method)
    {
        methodCalls.Add(method.Method.Name);

        return method.Invoke();
    }

    int spy(Func<string, int> method, string arg)
    {
        methodCalls.Add(method.Method.Name);

        return method.Invoke(arg);
    }

    private int spy(Func<int, int> method, int arg)
    {
        methodCalls.Add(method.Method.Name);

        return method.Invoke(arg);
    }

您看到了问题:我有几乎相同的方法块...有没有办法避免这种情况并仍然完成所需的行为?

好吧,您可以先将它们设为通用:

public TResult Spy<TResult>(Func<TResult> method)
{
    methodCalls.Add(method.Method.Name);
    return method();
}

public TResult Spy<TArg, TResult>(Func<TArg, TResult> method, TArg arg)
{
    methodCalls.Add(method.Method.Name);
    return method(arg);
}

public TResult Spy<TArg1, TArg2, TResult>
    (Func<TArg1, TArg2, TResult> method, TArg1 arg1, TArg2 arg2)
{
    methodCalls.Add(method.Method.Name);
    return method(arg1, arg2);
}

...

这至少意味着您只需要与要处理的最大参数数量一样多的重载。在不丢失编译时类型安全的情况下,您将无法轻易地做得比这更好。

首先,您需要用于要监视的 FuncAction 委托的通用方法。你需要这些方法来实现漂亮的强类型API。您还需要一个接受 Delegate 和参数列表的私有泛型方法。此方法将进行调用和记录:

public TResult Spy<TResult> (Func<TResult> method)
{
    return Spy<TResult>((Delegate)method);
}

public TResult Spy<T1, TResult> (Func<T1, TResult> method, T1 arg1)
{
    return Spy<TResult>((Delegate)method, arg1);
}

private TResult Spy<TResult> (Delegate method, params object[] args)
{
    methodCalls.Add(method.Method.Name);
    return (TResult)method.Method.Invoke(method.Target, args);
}

现在您可以传递带有零个或一个参数的任何方法,执行它们并记录方法名称,而不会出现任何重复。

基于您的主要目标

to have a "generic" - that is, a method with a single signature if possible instead of this rather copy/paste code below.

您可以尝试关注

object SpyUniversal(Delegate method, object[] args) 
{ 
  methodCalls.Add(method.Method.Name); 
  return method.Method.Invoke(null, args); 
}

请注意,如前所述,您正在失去编译时类型安全性。