我有许多使用相同模式的记录的方法。有些方法需要返回一些价值,有些方法不返回。我创建了一种具有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;
}
这不需要复制糊,但看起来不太好。
有一种方法可以以某种方式加入动作和功能,以避免任何这些方法,或者可能有另一种方法可以实现相同的结果?
第三选项是仍然超载
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
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());
}
如下:
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<>
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();
}
}
和异步委托与普通的对象一起传递到方法。