使用 Castle 动态代理的异步拦截
Async Interception using Castle 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);
});
}
我的任务 returns dynamic/object 而不是拦截 return 类型的 T。
我以为我可以像这样使用它
var task = PostAsync(client, url, parameters, returnType);
invocation.ReturnValue = task;
由于将 returned 的任务是原始任务并且它仍在等待中,我认为它可以工作但我得到的只是一个例外,即任务无法转换为我的类型的任务(在那种情况下是字符串)。
感谢帮手
编辑:
我确实看到了 ,这就是我尝试做的,但即使使用反射我也无法调用任务,我仍然遇到同样的异常。
我最终通过一些修改解决了它:
使用基础对象创建拦截器,我使用 Moq 对象来延迟创建它们并将它们存储在 ConcurrentDictionary 中以进行缓存。
var mock = new Mock<T>();
var pg = new ProxyGenerator();
return pg.CreateInterfaceProxyWithTarget<T>(GetTarget(clientType), _gatewayInterceptor);
我将调用的 return 值(在那种情况下是 T 的任务)传递给方法并获得了 T。
- 我用 T 的新任务包装了 http 调用,等待 http 调用并
return 反序列化任务的 T 结果。
将T的新任务分配回return值。
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
我正在尝试使用动态代理构建一个动态 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);
});
}
我的任务 returns dynamic/object 而不是拦截 return 类型的 T。
我以为我可以像这样使用它
var task = PostAsync(client, url, parameters, returnType);
invocation.ReturnValue = task;
由于将 returned 的任务是原始任务并且它仍在等待中,我认为它可以工作但我得到的只是一个例外,即任务无法转换为我的类型的任务(在那种情况下是字符串)。
感谢帮手
编辑:
我确实看到了
我最终通过一些修改解决了它:
使用基础对象创建拦截器,我使用 Moq 对象来延迟创建它们并将它们存储在 ConcurrentDictionary 中以进行缓存。
var mock = new Mock<T>(); var pg = new ProxyGenerator(); return pg.CreateInterfaceProxyWithTarget<T>(GetTarget(clientType), _gatewayInterceptor);
我将调用的 return 值(在那种情况下是 T 的任务)传递给方法并获得了 T。
- 我用 T 的新任务包装了 http 调用,等待 http 调用并 return 反序列化任务的 T 结果。
将T的新任务分配回return值。
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