使用Castle动态代理进行异步拦截

时间:2018-09-11 08:28:51

标签: c# generics task castle-dynamicproxy dynamic-proxy

我正在尝试使用动态代理来构建动态http客户端,以拦截呼叫并使用它创建一个http请求。

我遇到的问题是异步方法:

private Task<object> PostAsync(HttpClient client, string url, HttpRequestParameters parameters, Type returnType)
    {
        return Task.Run(async () =>
        {
            var requestContent = new StringContent(Serializer.Serialize(parameters.BodyParameters));
            var httpResponse = await client.PostAsync(url, requestContent);
            var responseContent = await httpResponse.Content.ReadAsStringAsync();
            return Serializer.Deserialize(responseContent, returnType);
        });
    }

我的任务返回动态/对象,而不是Interception返回类型的T。

我认为我将能够像这样使用它

 var task = PostAsync(client, url, parameters, returnType);
 invocation.ReturnValue = task;

由于将要返回的任务是原始任务,并且仍在待处理中,我认为它可以正常工作,但是我得到的是一个例外,即Task无法转换为我类型的任务(在这种情况下为字符串)。

感谢助手

编辑: 我确实看到了Intercept async method,这是我试图做的,但是即使使用反射也无法调用Task,但我仍然遇到相同的异常。

1 个答案:

答案 0 :(得分:2)

我最终做了一些修改来解决它:

  1. 使用基础对象创建拦截器,我使用Moq对象延迟创建它们并将它们存储在ConcurrentDictionary中进行缓存。

    var mock = new Mock<T>();
    var pg = new ProxyGenerator();
    return pg.CreateInterfaceProxyWithTarget<T>(GetTarget(clientType), _gatewayInterceptor);
    
  2. 我将调用的返回值(在这种情况下为T任务)传递给一个方法,并获得了T。

  3. 我用新的Task T包裹了http呼叫,等待http呼叫,然后 从任务中返回期望的T结果。
  4. 将新的T任务分配回返回值。

    invocation.ReturnValue = GetAsync((dynamic)invocation.ReturnValue, serializer, headers, req);
    
    internal static Task<T> GetAsync<T>(Task<T> originalTask, ISerializer serializer, Headers headers, InvokeHttpRequest req)
    {
        return Task.Run(async () =>
        {
            using (HttpClient client = new HttpClient())
            {
                var httpResponse = await PerformGetAsync(headers, req, client);
                var jsonResponse = await httpResponse.Content.ReadAsStringAsync();
                return ProcessResult<T>(serializer, jsonResponse);
            }
        });
    }
    

我知道这不是最好的方法,但是对我有用。 如果有人需要https://github.com/ErezLevip/SimpleProxyClient

,这里就是解决方案