gpt4 book ai didi

c# - 拦截通过 DynamicProxy 返回通用 Task<> 的异步方法

转载 作者:IT王子 更新时间:2023-10-29 04:19:01 27 4
gpt4 key购买 nike

我的问题与这篇文章有关Intercept the call to an async method using DynamicProxy

我想实现与返回 Task 的异步方法一起工作的拦截器或 Task<T>结果。

我使用下一个代码返回 ContinueWith结果(以便调用方方法在拦截器完成工作时等待)

var task = invocation.ReturnValue as Task;
invocation.ReturnValue = task.ContinueWith(c =>
{ code that should execute after method finish });

以上代码适用于 Task结果,但在 Task<T> 的情况下结果 ContinueWith将从 Task<T> 更改返回类型至 Task .我需要调用返回 Task<T> 的重载方法 ContinueWith , 但为此我需要投 invocation.ReturnValueTask<T>

我没有找到以任何方式动态转换它的方法。有人知道怎么做吗?

我也试过通过反射调用这个方法,但是参数是labmda函数,不能直接传过去。

最佳答案

经过广泛的研究,我能够创建一个适用于拦截同步方法以及异步任务和异步任务< TResult > 的解决方案。

这是我使用 CaSTLe Dynamic Proxy 的异常处理拦截器的代码,它适用于所有这些方法类型。此模式适用于执行您希望的任何类型的拦截。对于标准的 BeforeInvoke/AfterInvoke 操作,语法会更清晰一些,但概念应该是相同的。

(另请注意:示例中的 IExceptionHandler 接口(interface)是自定义类型,而不是普通对象。)

    private class AsyncExceptionHandlingInterceptor : IInterceptor
{
private static readonly MethodInfo handleAsyncMethodInfo = typeof(AsyncExceptionHandlingInterceptor).GetMethod("HandleAsyncWithResult", BindingFlags.Instance | BindingFlags.NonPublic);
private readonly IExceptionHandler _handler;

public AsyncExceptionHandlingInterceptor(IExceptionHandler handler)
{
_handler = handler;
}

public void Intercept(IInvocation invocation)
{
var delegateType = GetDelegateType(invocation);
if (delegateType == MethodType.Synchronous)
{
_handler.HandleExceptions(() => invocation.Proceed());
}
if (delegateType == MethodType.AsyncAction)
{
invocation.Proceed();
invocation.ReturnValue = HandleAsync((Task)invocation.ReturnValue);
}
if (delegateType == MethodType.AsyncFunction)
{
invocation.Proceed();
ExecuteHandleAsyncWithResultUsingReflection(invocation);
}
}

private void ExecuteHandleAsyncWithResultUsingReflection(IInvocation invocation)
{
var resultType = invocation.Method.ReturnType.GetGenericArguments()[0];
var mi = handleAsyncMethodInfo.MakeGenericMethod(resultType);
invocation.ReturnValue = mi.Invoke(this, new[] { invocation.ReturnValue });
}

private async Task HandleAsync(Task task)
{
await _handler.HandleExceptions(async () => await task);
}

private async Task<T> HandleAsyncWithResult<T>(Task<T> task)
{
return await _handler.HandleExceptions(async () => await task);
}

private MethodType GetDelegateType(IInvocation invocation)
{
var returnType = invocation.Method.ReturnType;
if (returnType == typeof(Task))
return MethodType.AsyncAction;
if (returnType.IsGenericType && returnType.GetGenericTypeDefinition() == typeof(Task<>))
return MethodType.AsyncFunction;
return MethodType.Synchronous;
}

private enum MethodType
{
Synchronous,
AsyncAction,
AsyncFunction
}
}

关于c# - 拦截通过 DynamicProxy 返回通用 Task<> 的异步方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28099669/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com