Nous avons essentiellement une classe qui ressemble à ceci ci-dessous qui utilise le Castle.DynamicProxy pour l'interception.Est-il possible de créer un intépteur asynchrone en utilisant 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.
}
}
....
Initialement ce code était:
Task.Run(async() => { await InterceptAsync(invocation, taskWrapper)).Wait()
Mais nous perdions HttpContext après tout appel à cela, nous avons donc dû passer à:
Task.Factory.StartNew
On pourrait donc passer the TaskScheduler.FromCurrentSynchronizationContext()
Tout cela est mauvais parce que nous sommes vraiment juste s wapping un fil pour un autre fil. J'aimerais vraiment changer la signature de
void IInterceptor.Intercept(IInvocation invocation)
à
async Task IInterceptor.Intercept(IInvocation invocation)
Et se débarrasser de la Task.Run ou Task.Factory et juste faire:
await InterceptAsync(invocation, taskWrapper);
Le problème Castle.DynamicProxy IInterecptor ne le permet pas. Je veux vraiment faire une attente dans l'Intercept. Je pourrais faire .Result mais alors quel est le point de l'appel asynchrone que j'appelle? Sans pouvoir faire l'attente je perds le bénéfice d'être capable de céder cette exécution de threads. Je ne suis pas coincé avec Castle Windsor pour leur DynamicProxy alors je suis à la recherche d'un autre moyen de le faire. Nous avons étudié Unity, mais je ne veux pas remplacer toute notre implémentation AutoFac.
Toute aide serait appréciée.
Merci pour le lien je vais vérifier et je vais donner un exemple à votre exemple. J'ai cherché des réponses à cela pendant des jours. –