如何避免重复多次覆盖方法接受Func <t,int =“”>作为参数

时间:2016-02-19 18:24:22

标签: c# generics func

我想要一个“通用” - 也就是说,如果可能的话,使用单一签名的方法 - 而不是下面的相当复制/粘贴代码。

我的目标是使用Spy Double

从第三方DLL“包装”方法
    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);
    }

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

3 个答案:

答案 0 :(得分:2)

嗯,你可以从使它们变得通用开始:

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

...

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

答案 1 :(得分:2)

首先,您需要要监视的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);
}

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

答案 2 :(得分:1)

基于您的主要目标

  

拥有“通用” - 也就是说,如果可能的话,使用单一签名的方法,而不是下面的复制/粘贴代码。

您可以尝试以下

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

请注意,您提到的编译时类型安全性正在下降。