5

我创建了一种方法来抽象 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()

4

4 回答 4

6

一种快速而肮脏的解决方案是在调用方法后添加默认值。Delete如果您不将Invoke方法的结果分配给变量,它将被忽略。例如,下面的代码演示了这一点:

Invoke(() => {CustomVariableGroupLogic.Delete(customVariableGroup); return 0; });

你可以在这里看到类似的例子,

如果您有很多这样的调用,您可以构建一个精美的包装器,它将返回Func给定的Action. 例子:

Func<Action, Func<int>> wrap = action => () => {action(); return 0;};

现在你可以

Invoke(() => wrap(() => CustomVariableGroupLogic.Delete(customVariableGroup)));

但这有点接近 lambda 疯狂

灵感来自 pcm2

您可以创建一个重载 to Invoke,它只是Action作为参数,使用上面提出的解决方案来调用实现Func<T>

public void Invoke(Action action)
{
    Invoke(() => {action(); return 0;});
}

现在你可以

Invoke(() => CustomVariableGroupLogic.Delete(customVariableGroup));
于 2013-06-04T19:56:24.363 回答
2

你不能只创建一个调用的重载吗?

public void Invoke<T>(Func<T> func){
    return (T) InvokeInternal(func);
}

public void Invoke(Action action){
    InvokeInternal(action);
}

如果您希望这两种方法都做完全相同的事情,并保持干燥,您可以创建一个像这样的方法:

private object InvokeInternal(System.Delegate @delegate)
{
    try
    {
        return @delegate.DynamicInvoke();
    }
    catch (Exception ex)
    {
        throw LogAndThrowFaultException(ex);
    }
}

并且让你的两个重载都调用这个方法,适当地转换结果,如果有的话

于 2013-06-04T19:59:07.103 回答
1
  1. 你真的必须func.Invoke()吗?为什么不只是func()
  2. 为什么不是你的Invoke静电?
  3. 根据LogAndThrowFaultException正在做的事情,这可能非常糟糕。通过始终将内部异常设置为 来确保保留异常堆栈ex

但是,是的,您需要第二个函数返回 void 而不是 T。

于 2013-06-04T19:54:52.153 回答
1

您可以像这样将动作包装成一个函数。或者您可以创建一个方便的函数来进行包装:

void Main()
{
    Action<string> a = s => Console.WriteLine(s);

    Invoke(() => { a(); return null; });
    Invoke(s);
}

private void Invoke(Action a)
{
    Invoke(() => { a(); return null; };
}
于 2013-06-04T19:59:13.730 回答