在一个参数中进行操作和弹性

问题描述 投票:0回答:4

我有许多使用相同模式的记录的方法。有些方法需要返回一些价值,有些方法不返回。我创建了一种具有Action参数的方法,以避免复制所有逻辑。看起来这样:

private void Execute(Action action)
{
   Logger.Start();
   try
   {
      action();
   }
   catch(Exception exception)
   {
      Logger.WriteException();
      throw;
   }
   finally
   {
       Logger.Finish();
   }
}

现在我有一些像那样的电话

public void DoSomething(string parameter)
{
    Execute(() => GetProvider(parameter).DoSomething());
}

但是我需要一些返回值的函数。什么是最好的方法? 我现在找到了两个:

1)用func

创建执行方法的副本
private T Execute<T>(Func<T> action)
{
   Logger.Start();
   try
   {
      return action();
   }
   catch(Exception exception)
   {
      Logger.WriteException();
      throw;
   }
   finally
   {
       Logger.Finish();
   }
}

这种方法有效,但也有一些复制糊状。

2)将参数欺骗为一个动作:

public Result DoSomething(string parameter) { Result result = null; Execute(() => result = GetProvider(parameter).DoSomething()); return result; }
这不需要复制糊,但看起来不太好。

有一种方法可以以某种方式加入动作和功能,以避免任何这些方法,或者可能有另一种方法可以实现相同的结果?

第三选项是仍然超载
c# .net delegates action func
4个回答
7
投票
,但要使

Action

版本以
Func
版本的方式工作:
private void Execute(Action action)
{
    // We just ignore the return value here
    Execute(() => { 
        action();
        return 0; 
    });
}
当然,如果

void
更像是“真实”类型(例如f#et al中的
Unit

),那么所有这些都会更简单,这时我们可以拥有

Task<T>
而不是
Task
Task<T>
也...
    
创建了将

Execute

3
投票
Func

的副本。您只需要一次编写一个丑陋的代码,而最终不会获得

Action
方法的完整第二副本:
Execute
    
这里是另一种选择。与其让记录框架调用您的实际代码,不如将实际代码调用记录框架。这样的事情可以解决问题(非常简化)。

private T Execute<T>(Func<T> func) { T result = default(T); this.Execute(() => { result = func(); }); return result; } ... public Result DoSomething(string parameter) { return Execute(() => GetProvider(parameter).DoSomething()); }
如下:

2
投票
public class LoggerScope : IDisposable { private bool disposed; public LoggerScope() { Logger.Start(); } public void Dispose() { if(!disposed) { Logger.Finish(); disposed = true; } } }

通过在代码的最高级别捕获和记录一次,单独捕获和记录它们。 thevantages:

避免到处都是lambdas的需求,因此异常的堆栈跟踪有点清洁。 您可以在

using(var scope = new LoggerScope()) { // actual code goes here }
类中添加任意上下文数据,例如GUID,时间戳,逻辑任务说明文本。

您还可以使用支持

LoggerScope

    System.Delegate
  • 分配的
  • System.MulticastDelegate
  • Action
    。然后,您可以在代表上致电
  • Func<>
并根据结果继续进行。 我建议采用以下方法:

0
投票
DynamicInvoke()

这种方式您可以将
public async void ExecuteAsync(Delegate action) { Logger.Start(); try { var result = action.DynamicInvoke(); if (result is Task task) await task; } catch (Exception exception) { Logger.WriteException(); throw; } finally { Logger.Finish(); } }
和异步委托与普通的对象一起传递到方法。
    

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.