首页 > 解决方案 > 可以拦截异步方法并覆盖 ReturnValue?

问题描述

我有一个方法:

public virtual async Task<IActionResult> GetEmployees([HttpTrigger(AuthorizationLevel.Admin, "get", Route = null)] HttpRequest req) {
  return OkObjectResult(null);
}

我知道我可以使用 autofac 同步拦截:

public class CallLogger : IInterceptor
{
  TextWriter _output;

  public CallLogger(TextWriter output)
  {
    _output = output;
  }

 public void Intercept(IInvocation invocation)
  {
    _output.Write("Calling method {0} with parameters {1}... ",
      invocation.Method.Name,
      string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray()));

    invocation.Proceed();

    _output.WriteLine("Done: result was {0}.", invocation.ReturnValue);
  }
}

但是,如何在可能覆盖我正在拦截的方法返回的结果的同时异步执行此操作?它当前返回一个OkObjectResult,例如,我可能想返回一个 404。

伪代码

public async Task Intercept(IInvocation invocation)
{
    var myAsyncResult = await _myAsyncClass.MyAsyncMethod();

    if (myAsyncResult == expected)
    {
       invocation.Proceed();
    }
    else
    {
       invocation.ReturnValue = // some overwrite of the value - and don't proceed with the invocation.
    }
}

笔记

我知道在 autofac 中有聪明的异步方法,但这不允许我阻止执行原始方法并覆盖值,而是我需要“继续”调用并使用它的返回:https://stackoverflow。 com/a/39784559/12683473

标签: c#.netautofacinterceptor

解决方案


Castle.Core 要记住的主要事情是,您不能IInvocation.Proceed在 an 之后调用,await因为IInvocation实例在拦截器(同步)返回后被重用。

但是,Castle.Core 的现代版本确实支持IInvocation.CaptureProceedInfo,可以这样使用:

public class CallLogger : IInterceptor
{
  public void Intercept(IInvocation invocation)
  {
    invocation.ReturnValue = InterceptAsync<MyResult>(invocation.CaptureProceedInfo());
  }

  private async Task<TResult> InterceptAsync<TResult>(IInvocationProceedInfo proceed)
  {
    var myAsyncResult = await _myAsyncClass.MyAsyncMethod();

    if (myAsyncResult == expected)
    {
      proceed.Invoke();
    }
    else
    {
      return ...;
    }
  }
}

这个简单的代码假定您的代码可以指定一种类型MyResult,该类型是被拦截方法的已知结果。更一般的情况需要反思和TaskCompletionSource<T>.


推荐阅读