В основном у нас есть класс, который выглядит следующим образом, который использует Castle.DynamicProxy для перехвата.Можно ли создать асинхронный inteceptor с помощью Castle.DynamicProxy?
using System;
using System.Collections.Concurrent;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Castle.DynamicProxy;
namespace SaaS.Core.IoC
{
public abstract class AsyncInterceptor : IInterceptor
{
private readonly ILog _logger;
private readonly ConcurrentDictionary<Type, Func<Task, IInvocation, Task>> wrapperCreators =
new ConcurrentDictionary<Type, Func<Task, IInvocation, Task>>();
protected AsyncInterceptor(ILog logger)
{
_logger = logger;
}
void IInterceptor.Intercept(IInvocation invocation)
{
if (!typeof(Task).IsAssignableFrom(invocation.Method.ReturnType))
{
InterceptSync(invocation);
return;
}
try
{
CheckCurrentSyncronizationContext();
var method = invocation.Method;
if ((method != null) && typeof(Task).IsAssignableFrom(method.ReturnType))
{
var taskWrapper = GetWrapperCreator(method.ReturnType);
Task.Factory.StartNew(
async() => { await InterceptAsync(invocation, taskWrapper).ConfigureAwait(true); }
, // this will use current synchronization context
CancellationToken.None,
TaskCreationOptions.AttachedToParent,
TaskScheduler.FromCurrentSynchronizationContext()).Wait();
}
}
catch (Exception ex)
{
//this is not really burring the exception
//excepiton is going back in the invocation.ReturnValue which
//is a Task that failed. with the same excpetion
//as ex.
}
}
....
Первоначально этот код был:
Task.Run(async() => { await InterceptAsync(invocation, taskWrapper)).Wait()
Но мы проигрывали HttpContext после любого вызова к этому, поэтому пришлось переключить его на:
Task.Factory.StartNew
Таким образом, мы могли бы пройти в TaskScheduler.FromCurrentSynchronizationContext()
Все это плохо, потому что мы действительно просто с wapping один поток для другого потока. Я бы очень хотелось, чтобы изменить подпись
void IInterceptor.Intercept(IInvocation invocation)
в
async Task IInterceptor.Intercept(IInvocation invocation)
И избавиться от Task.Run или Task.Factory и просто сделать это:
await InterceptAsync(invocation, taskWrapper);
Проблема это Castle.DynamicProxy IInterecptor не позволит этого. Я действительно хочу сделать ожидание в Intercept. Я мог бы сделать. Результат, но тогда в чем смысл асинхронного вызова, который я звоню? Не имея возможности сделать это, я проиграю из того, что он сможет выполнить это выполнение потоков. Я не придерживаюсь Castle Windsor для своего DynamicProxy, поэтому я ищу другой способ сделать это. Мы рассмотрели Unity, но я не хочу заменять всю реализацию AutoFac.
Любая помощь будет оценена по достоинству.
Спасибо за ссылку, я проверю ее, и я приведу ваш пример. Я искал ответы на это в течение нескольких дней. –