下面是从代码Intercept上实现自定义类型的方法IInterceptor的的城堡动态代理库.此片段来自此处发布的基于AOP的日志记录概念验证控制台应用程序.
public void Intercept(IInvocation invocation)
{
if (Log.IsDebugEnabled) Log.Debug(CreateInvocationLogString("Called", invocation));
try
{
invocation.Proceed();
if (Log.IsDebugEnabled)
if (invocation.Method.ReturnType != typeof(void))
Log.Debug("Returning with: " + invocation.ReturnValue);
}
catch (Exception ex)
{
if (Log.IsErrorEnabled) Log.Error(CreateInvocationLogString("ERROR", invocation), ex);
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
这在常规方法调用中按预期工作,但在尝试使用async方法时(使用async/awaitC#5.0中的关键字)则不行.我相信,我也理解这背后的原因.
为了async/await工作,编译器将方法的功能主体添加到幕后的状态机中,并且一旦awaitable遇到无法同步完成的第一个表达式,控件将返回到调用者.
此外,我们可以询问返回类型并确定我们是否正在处理这样的async方法:
if (invocation.Method.ReturnType == typeof(Task) ||
(invocation.Method.ReturnType.IsGenericType &&
invocation.Method.ReturnType.GetGenericTypeDefinition() == typeof(Task<>)))
Log.Info("Asynchronous method found...");
Run Code Online (Sandbox Code Playgroud)
这适用于那些async返回Task或Task<>不返回的方法, …
我们基本上有一个如下所示的类,它使用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 () => …Run Code Online (Sandbox Code Playgroud) 所以我有这门课:
public class MappingBootstrap : IMappingBootstrap
{
public virtual async Task Map()
{
// Order is very important
await this.mapper1.Map();
await this.mapper2.Map();
await this.mapper3.Map();
await this.mapper4.Map();
}
}
Run Code Online (Sandbox Code Playgroud)
我有Autofac拦截器:
public class LoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
var methodReference = Guid.NewGuid();
Console.WriteLine($"Calling {invocation?.Method?.DeclaringType?.Name}.{invocation?.Method?.Name} : {methodReference}");
var startNew = Stopwatch.StartNew();
invocation?.Proceed();
startNew.Stop();
Console.WriteLine($"{methodReference} : Done, time taken: {startNew.ElapsedMilliseconds}ms");
}
}
Run Code Online (Sandbox Code Playgroud)
这会产生输出:
调用IMapperBootstrap.Map:54425559-71fe-4f23-ab47-d0f3371ec819
调用IMapper1.Map:51babb34-fa83-42ed-84e7-a1e979528116
51babb34-fa83-42ed-84e7-a1e979528116:完成,所用时间:219ms
54425559-71fe-4f23- ab47-d0f3371ec819:完成,所用时间:221ms
呼叫IMapper2.Map:41c812a2-d82d-48f6-9b8d-139b52eb28e3
41c812a2-d82d-48f6-9b8d-139b52eb28e3:完成,所用时间:9ms
呼叫IMapper3.Map:c91bed04-8f86-47d3 -a35a-417e354c2c5f
c91bed04-8f86-47d3-a35a-417e354c2c5f:完成,所需时间:994ms
调用IMapper4.Map:035cad27-1ba8-4bd1-b85f-396f64998d97
035cad27-1ba8-4bd1-b85f-396f64998d97:完成,所用时间:18ms
正如您所看到的,MappingBoostrap.Map完成后的第一个Mapper1.Map而不是我期望的所有功能完成后的结束. …