还使用func方法进行操作?

时间:2013-06-04 19:51:43

标签: c# action func

我创建了一个抽象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));

但是,我不能在那里使用voidInvoke()方法需要func,但在这种情况下,它必须是action。我做了一些研究,看起来我可能需要创建另一个Invoke()方法,但需要采取行动。这些建议来自2009年和2010年。是否有可能以某种方式使用我的func方法而无需创建另一个Invoke()方法,如Invoke2()

4 个答案:

答案 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)

  1. 你真的需要func.Invoke()吗?为什么不只是func()
  2. 为什么不是您的Invoke静态?
  3. 根据LogAndThrowFaultException正在做什么,这可能非常糟糕。通过始终将内部异常设置为ex来确保保留异常堆栈。
  4. 但是,是的,你需要第二个返回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; };
}