我创建了一个抽象try / catch功能的方法。我有大约30种方法具有完全相同的try / catch方案。所以我把它放在一个方法中:
private T Invoke<T>(Func<T> func)
{
try
{
return func.Invoke();
}
catch (Exception ex)
{
throw LogAndThrowFaultException(ex);
}
}
现在,大多数方法都是这样称呼的:
public IEnumerable<PingResponse> GetAllForPingRequest(PingRequest pingRequest)
{
return Invoke(() => PingResponseLogic.GetAllForPingRequest(pingRequest));
}
我的问题是我只有几种方法可以调用它而无需返回值:
Invoke<void>(() => CustomVariableGroupLogic.Delete(customVariableGroup));
但是,我不能在那里使用void
。 Invoke()
方法需要func
,但在这种情况下,它必须是action
。我做了一些研究,看起来我可能需要创建另一个Invoke()
方法,但需要采取行动。这些建议来自2009年和2010年。是否有可能以某种方式使用我的func方法而无需创建另一个Invoke()
方法,如Invoke2()
?
答案 0 :(得分:6)
一个快速而肮脏的解决方案是在调用Delete
方法后添加默认值。如果不将Invoke
方法的结果赋给变量,则无论如何都会被忽略。例如,下一个代码演示了这一点:
Invoke(() => {CustomVariableGroupLogic.Delete(customVariableGroup); return 0; });
您可以看到提议的类似示例here,
如果您有很多这样的调用,您可以构建一个花哨的包装器,它将返回给定Func
的{{1}}。例如:
Action
现在你可以
Func<Action, Func<int>> wrap = action => () => {action(); return 0;};
但这有点接近lambda craziness
受pcm2的启发:
您可以为Invoke(() => wrap(() => CustomVariableGroupLogic.Delete(customVariableGroup)));
创建一个重载,只需将Invoke
作为参数,使用上面提出的解决方案来调用Action
的实现:
Func<T>
现在你可以
了public void Invoke(Action action)
{
Invoke(() => {action(); return 0;});
}
答案 1 :(得分:2)
你能不能只创建一个调用重载?
public void Invoke<T>(Func<T> func){
return (T) InvokeInternal(func);
}
public void Invoke(Action action){
InvokeInternal(action);
}
如果你想要两种方法做同样的事情,并保持DRY,你可以创建一个这样的方法:
private object InvokeInternal(System.Delegate @delegate)
{
try
{
return @delegate.DynamicInvoke();
}
catch (Exception ex)
{
throw LogAndThrowFaultException(ex);
}
}
让你的重载都调用这个方法,适当地转换结果,如果有的话
答案 2 :(得分:1)
func.Invoke()
吗?为什么不只是func()
?Invoke
静态?LogAndThrowFaultException
正在做什么,这可能非常糟糕。通过始终将内部异常设置为ex
来确保保留异常堆栈。但是,是的,你需要第二个返回void而不是T的函数。
答案 3 :(得分:1)
你可以将动作包装成这样的func。或者你可以创建一个包装的便利功能:
void Main()
{
Action<string> a = s => Console.WriteLine(s);
Invoke(() => { a(); return null; });
Invoke(s);
}
private void Invoke(Action a)
{
Invoke(() => { a(); return null; };
}