我想要一个“通用” - 也就是说,如果可能的话,使用单一签名的方法 - 而不是下面的相当复制/粘贴代码。
我的目标是使用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);
}
你看到了问题:我有几乎相同的方法块......有没有办法避免这种情况并仍能完成所需的行为?
答案 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)
首先,您需要要监视的Func
和Action
个委托的通用方法。你需要这些方法来实现强类型的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);
}
请注意,您提到的编译时类型安全性正在下降。