Improved interception.

pull/96/head
Halil İbrahim Kalkan 9 years ago
parent 3221775900
commit 343a9b38af

@ -2,7 +2,6 @@
using Castle.DynamicProxy;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Threading;
using Volo.ExtensionMethods;
namespace Volo.Abp.Castle.DynamicProxy
{
@ -37,19 +36,18 @@ namespace Volo.Abp.Castle.DynamicProxy
else
{
var interceptResult = _abpInterceptor.InterceptAsync(new CastleAbpMethodInvocationAdapter(invocation));
invocation.ReturnValue = InternalAsyncHelper.CallAwaitTaskWithPostActionAndFinallyAndGetResult(
var actualReturnValue = invocation.ReturnValue;
invocation.ReturnValue = InternalAsyncHelper.CallAwaitTaskWithPreActionAndPostActionAndFinallyAndGetResult(
invocation.Method.ReturnType.GenericTypeArguments[0],
invocation.ReturnValue, //TODO: Can not change return value in that case !!! Create an interceptor that changes return value, for test purposes!
() => interceptResult,
exception => { }
() => actualReturnValue,
() => interceptResult
);
}
}
private void InterceptSyncMethod(IInvocation invocation)
{
AsyncHelper.RunSync(() => _abpInterceptor.InterceptAsync(new CastleAbpMethodInvocationAdapter(invocation)));
_abpInterceptor.Intercept(new CastleAbpMethodInvocationAdapter(invocation));
}
}
}

@ -30,34 +30,28 @@ namespace Volo.Abp.Castle.DynamicProxy
Invocation = invocation;
}
public Task ProceedAsync()
{
return Invocation.Method.IsAsync()
? RunAsync()
: RunSync();
}
public void Proceed()
{
Invocation.Proceed();
private Task RunAsync()
{
Invocation.Proceed();
return (Task) Invocation.ReturnValue;
}
if (Invocation.Method.IsAsync())
{
AsyncHelper.RunSync(() => (Task) Invocation.ReturnValue);
}
}
private Task RunSync()
public Task ProceedAsync()
{
Invocation.Proceed();
if (Method.ReturnType == typeof(void))
{
return Task.CompletedTask;
}
else
{
return (Task) typeof(Task)
.GetMethod("FromResult", BindingFlags.Static | BindingFlags.Public)
.MakeGenericMethod(Method.ReturnType)
.Invoke(null, new object[] {Invocation.ReturnValue});
}
}
}
Invocation.Proceed();
if (Invocation.Method.IsAsync())
{
return (Task)Invocation.ReturnValue;
}
else
{
return Task.FromResult(Invocation.ReturnValue);
}
}
}
}

@ -0,0 +1,15 @@
using System.Threading.Tasks;
namespace Volo.Abp.DynamicProxy
{
public abstract class AbpInterceptor : IAbpInterceptor
{
public abstract void Intercept(IAbpMethodInvocation invocation);
public virtual Task InterceptAsync(IAbpMethodInvocation invocation)
{
Intercept(invocation);
return Task.CompletedTask;
}
}
}

@ -2,8 +2,11 @@
namespace Volo.Abp.DynamicProxy
{
public interface IAbpInterceptor
//TODO: Create also Intercept() for sync method interception! Create AbpInterceptor for simpler usage!
public interface IAbpInterceptor
{
void Intercept(IAbpMethodInvocation invocation);
Task InterceptAsync(IAbpMethodInvocation invocation);
}
}
}

@ -16,6 +16,8 @@ namespace Volo.Abp.DynamicProxy
object ReturnValue { get; set; }
Task ProceedAsync();
void Proceed();
Task ProceedAsync();
}
}

@ -1,181 +1,193 @@
using System;
using System.Reflection;
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace Volo.Abp.Threading
{
public static class InternalAsyncHelper //TODO: Rename since it's not internal anymore!
{
public static async Task AwaitTaskWithFinally(Task actualReturnValue, Action<Exception> finalAction)
{
Exception exception = null;
try
{
await actualReturnValue;
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
finalAction(exception);
}
}
public static async Task AwaitTaskWithPostActionAndFinally(Task actualReturnValue, Func<Task> postAction, Action<Exception> finalAction)
{
Exception exception = null;
try
{
await actualReturnValue;
await postAction();
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
finalAction(exception);
}
}
public static async Task AwaitTaskWithPreActionAndPostActionAndFinally(Func<Task> actualReturnValue, Func<Task> preAction = null, Func<Task> postAction = null, Action<Exception> finalAction = null)
{
Exception exception = null;
try
{
if (preAction != null)
{
await preAction();
}
await actualReturnValue();
if (postAction != null)
{
await postAction();
}
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
if (finalAction != null)
{
finalAction(exception);
}
}
}
public static async Task<T> AwaitTaskWithFinallyAndGetResult<T>(Task<T> actualReturnValue, Action<Exception> finalAction)
{
Exception exception = null;
try
{
return await actualReturnValue;
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
finalAction(exception);
}
}
public static object CallAwaitTaskWithFinallyAndGetResult(Type taskReturnType, object actualReturnValue, Action<Exception> finalAction)
{
return typeof(InternalAsyncHelper)
.GetTypeInfo()
.GetMethod("AwaitTaskWithFinallyAndGetResult", BindingFlags.Public | BindingFlags.Static)
.MakeGenericMethod(taskReturnType)
.Invoke(null, new object[] { actualReturnValue, finalAction });
}
public static async Task<T> AwaitTaskWithPostActionAndFinallyAndGetResult<T>(Task<T> actualReturnValue, Func<Task> postAction, Action<Exception> finalAction)
{
Exception exception = null;
try
{
var result = await actualReturnValue;
await postAction();
return result;
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
finalAction(exception);
}
}
public static object CallAwaitTaskWithPostActionAndFinallyAndGetResult(Type taskReturnType, object actualReturnValue, Func<Task> action, Action<Exception> finalAction)
{
return typeof (InternalAsyncHelper)
.GetTypeInfo()
.GetMethod("AwaitTaskWithPostActionAndFinallyAndGetResult", BindingFlags.Public | BindingFlags.Static)
.MakeGenericMethod(taskReturnType)
.Invoke(null, new object[] { actualReturnValue, action, finalAction });
}
public static async Task<T> AwaitTaskWithPreActionAndPostActionAndFinallyAndGetResult<T>(Func<Task<T>> actualReturnValue, Func<Task> preAction = null, Func<Task> postAction = null, Action<Exception> finalAction = null)
{
Exception exception = null;
try
{
if (preAction != null)
{
await preAction();
}
var result = await actualReturnValue();
if (postAction != null)
{
await postAction();
}
return result;
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
if (finalAction != null)
{
finalAction(exception);
}
}
}
public static object CallAwaitTaskWithPreActionAndPostActionAndFinallyAndGetResult(Type taskReturnType, Func<object> actualReturnValue, Func<Task> preAction = null, Func<Task> postAction = null, Action<Exception> finalAction = null)
{
return typeof(InternalAsyncHelper)
.GetTypeInfo()
.GetMethod("AwaitTaskWithPreActionAndPostActionAndFinallyAndGetResult", BindingFlags.Public | BindingFlags.Static)
.MakeGenericMethod(taskReturnType)
.Invoke(null, new object[] { actualReturnValue, preAction, postAction, finalAction });
}
}
//TODO: Rename since it's not internal anymore!
//TODO: Cache GetMethod reflection!
public static class InternalAsyncHelper
{
public static async Task AwaitTaskWithFinally(Task actualReturnValue, Action<Exception> finalAction)
{
Exception exception = null;
try
{
await actualReturnValue;
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
finalAction(exception);
}
}
public static async Task AwaitTaskWithPostActionAndFinally(Task actualReturnValue, Func<Task> postAction, Action<Exception> finalAction)
{
Exception exception = null;
try
{
await actualReturnValue;
await postAction();
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
finalAction(exception);
}
}
public static async Task AwaitTaskWithPreActionAndPostActionAndFinally(Func<Task> actualReturnValue, Func<Task> preAction = null, Func<Task> postAction = null, Action<Exception> finalAction = null)
{
Exception exception = null;
try
{
if (preAction != null)
{
await preAction();
}
await actualReturnValue();
if (postAction != null)
{
await postAction();
}
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
if (finalAction != null)
{
finalAction(exception);
}
}
}
public static async Task<T> AwaitTaskWithFinallyAndGetResult<T>(Task<T> actualReturnValue, Action<Exception> finalAction)
{
Exception exception = null;
try
{
return await actualReturnValue;
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
finalAction(exception);
}
}
public static object CallAwaitTaskWithFinallyAndGetResult(Type taskReturnType, object actualReturnValue, Action<Exception> finalAction)
{
return typeof(InternalAsyncHelper)
.GetTypeInfo()
.GetMethod("AwaitTaskWithFinallyAndGetResult", BindingFlags.Public | BindingFlags.Static)
.MakeGenericMethod(taskReturnType)
.Invoke(null, new object[] { actualReturnValue, finalAction });
}
public static async Task<T> AwaitTaskWithPostActionAndFinallyAndGetResult<T>(Task<T> actualReturnValue, Func<Task> postAction, Action<Exception> finalAction)
{
Exception exception = null;
try
{
var result = await actualReturnValue;
await postAction();
return result;
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
finalAction(exception);
}
}
public static object CallAwaitTaskWithPostActionAndFinallyAndGetResult(Type taskReturnType, object actualReturnValue, Func<Task> action, Action<Exception> finalAction)
{
return typeof(InternalAsyncHelper)
.GetTypeInfo()
.GetMethod("AwaitTaskWithPostActionAndFinallyAndGetResult", BindingFlags.Public | BindingFlags.Static)
.MakeGenericMethod(taskReturnType)
.Invoke(null, new object[] { actualReturnValue, action, finalAction });
}
public static async Task<T> AwaitTaskWithPreActionAndPostActionAndFinallyAndGetResult<T>(Func<Task<T>> actualReturnValue, Func<Task> preAction = null, Func<Task> postAction = null, Action<Exception> finalAction = null)
{
Exception exception = null;
try
{
if (preAction != null)
{
await preAction();
}
var result = await actualReturnValue();
if (postAction != null)
{
await postAction();
}
return result;
}
catch (Exception ex)
{
exception = ex;
throw;
}
finally
{
finalAction?.Invoke(exception);
}
}
public static object CallAwaitTaskWithPreActionAndPostActionAndFinallyAndGetResult(Type taskReturnType, Func<object> actualReturnValue, Func<Task> preAction = null, Func<Task> postAction = null, Action<Exception> finalAction = null)
{
var returnFunc = typeof(InternalAsyncHelper)
.GetTypeInfo()
.GetMethod("ConvertFuncOfObjectToFuncOfTask", BindingFlags.NonPublic | BindingFlags.Static)
.MakeGenericMethod(taskReturnType)
.Invoke(null, new object[] {actualReturnValue});
return typeof(InternalAsyncHelper)
.GetTypeInfo()
.GetMethod("AwaitTaskWithPreActionAndPostActionAndFinallyAndGetResult", BindingFlags.Public | BindingFlags.Static)
.MakeGenericMethod(taskReturnType)
.Invoke(null, new object[] { returnFunc, preAction, postAction, finalAction });
}
[UsedImplicitly]
private static Func<Task<T>> ConvertFuncOfObjectToFuncOfTask<T>(Func<object> actualReturnValue)
{
return () => (Task<T>)actualReturnValue();
}
}
}

@ -4,7 +4,7 @@ using Volo.DependencyInjection;
namespace Volo.Abp.Uow
{
public class UnitOfWorkInterceptor : IAbpInterceptor, ITransientDependency
public class UnitOfWorkInterceptor : AbpInterceptor, ITransientDependency
{
private readonly IUnitOfWorkManager _unitOfWorkManager;
@ -13,7 +13,18 @@ namespace Volo.Abp.Uow
_unitOfWorkManager = unitOfWorkManager;
}
public async Task InterceptAsync(IAbpMethodInvocation invocation)
public override void Intercept(IAbpMethodInvocation invocation)
{
//TODO: Check UOW attribute and other conditions!
using (var uow = _unitOfWorkManager.Begin())
{
invocation.Proceed();
uow.Complete();
}
}
public override async Task InterceptAsync(IAbpMethodInvocation invocation)
{
//TODO: Check UOW attribute and other conditions!

@ -1,14 +1,13 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Castle.DynamicProxy;
using Xunit;
namespace Volo.Abp.Autofac.Interception
{
public class Autofac_Interception_Test : CastleInterceptionTestBase<AutofacTestModule>
{
//TODO: Sımplify using autofac in tests!
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
@ -18,95 +17,5 @@ namespace Volo.Abp.Autofac.Interception
{
return services.BuildAutofacServiceProvider();
}
[Fact]
public async Task Should_Intercept_Async_Method_Without_Return_Value()
{
//Arrange
var target = ServiceProvider.GetService<SimpleInterceptionTargetClass>();
//Act
await target.DoItAsync();
//Assert
target.Logs.Count.ShouldBe(7);
target.Logs[0].ShouldBe("SimpleInterceptor_BeforeInvocation");
target.Logs[1].ShouldBe("SimpleInterceptor2_BeforeInvocation");
target.Logs[2].ShouldBe("EnterDoItAsync");
target.Logs[3].ShouldBe("MiddleDoItAsync");
target.Logs[4].ShouldBe("ExitDoItAsync");
target.Logs[5].ShouldBe("SimpleInterceptor2_AfterInvocation");
target.Logs[6].ShouldBe("SimpleInterceptor_AfterInvocation");
}
[Fact]
public async Task Should_Intercept_Async_Method_With_Return_Value()
{
//Arrange
var target = ServiceProvider.GetService<SimpleInterceptionTargetClass>();
//Act
var result = await target.GetValueAsync();
//Assert
result.ShouldBe(42);
target.Logs.Count.ShouldBe(7);
target.Logs[0].ShouldBe("SimpleInterceptor_BeforeInvocation");
target.Logs[1].ShouldBe("SimpleInterceptor2_BeforeInvocation");
target.Logs[2].ShouldBe("EnterGetValueAsync");
target.Logs[3].ShouldBe("MiddleGetValueAsync");
target.Logs[4].ShouldBe("ExitGetValueAsync");
target.Logs[5].ShouldBe("SimpleInterceptor2_AfterInvocation");
target.Logs[6].ShouldBe("SimpleInterceptor_AfterInvocation");
}
[Fact]
public void Should_Intercept_Sync_Method_Without_Return_Value()
{
//Arrange
var target = ServiceProvider.GetService<SimpleInterceptionTargetClass>();
//Act
target.DoIt();
//Assert
target.Logs.Count.ShouldBe(5);
target.Logs[0].ShouldBe("SimpleInterceptor_BeforeInvocation");
target.Logs[1].ShouldBe("SimpleInterceptor2_BeforeInvocation");
target.Logs[2].ShouldBe("ExecutingDoIt");
target.Logs[3].ShouldBe("SimpleInterceptor2_AfterInvocation");
target.Logs[4].ShouldBe("SimpleInterceptor_AfterInvocation");
}
[Fact]
public void Should_Intercept_Sync_Method_With_Return_Value()
{
//Arrange
var target = ServiceProvider.GetService<SimpleInterceptionTargetClass>();
//Act
var result = target.GetValue();
//Assert
result.ShouldBe(42);
target.Logs.Count.ShouldBe(5);
target.Logs[0].ShouldBe("SimpleInterceptor_BeforeInvocation");
target.Logs[1].ShouldBe("SimpleInterceptor2_BeforeInvocation");
target.Logs[2].ShouldBe("ExecutingGetValue");
target.Logs[3].ShouldBe("SimpleInterceptor2_AfterInvocation");
target.Logs[4].ShouldBe("SimpleInterceptor_AfterInvocation");
}
}
}
}

@ -22,8 +22,9 @@ namespace Volo.Abp.Castle
//TODO: Create an attribute to add interceptors!
if (typeof(SimpleInterceptionTargetClass) == registration.ImplementationType)
{
registration.Interceptors.Add<SimpleInterceptor>();
registration.Interceptors.Add<SimpleInterceptor2>();
registration.Interceptors.Add<SimpleAsyncInterceptor>();
registration.Interceptors.Add<SimpleSyncInterceptor>();
registration.Interceptors.Add<SimpleAsyncInterceptor2>();
}
}
}

@ -11,6 +11,101 @@ namespace Volo.Abp.Castle.DynamicProxy
public abstract class CastleInterceptionTestBase<TStartupModule> : AbpIntegratedTest<TStartupModule>
where TStartupModule : IAbpModule
{
[Fact]
public async Task Should_Intercept_Async_Method_Without_Return_Value()
{
//Arrange
}
var target = ServiceProvider.GetService<SimpleInterceptionTargetClass>();
//Act
await target.DoItAsync();
//Assert
target.Logs.Count.ShouldBe(9);
target.Logs[0].ShouldBe("SimpleAsyncInterceptor_InterceptAsync_BeforeInvocation");
target.Logs[1].ShouldBe("SimpleSyncInterceptor_Intercept_BeforeInvocation");
target.Logs[2].ShouldBe("SimpleAsyncInterceptor2_InterceptAsync_BeforeInvocation");
target.Logs[3].ShouldBe("EnterDoItAsync");
target.Logs[4].ShouldBe("MiddleDoItAsync");
target.Logs[5].ShouldBe("ExitDoItAsync");
target.Logs[6].ShouldBe("SimpleAsyncInterceptor2_InterceptAsync_AfterInvocation");
target.Logs[7].ShouldBe("SimpleSyncInterceptor_Intercept_AfterInvocation");
target.Logs[8].ShouldBe("SimpleAsyncInterceptor_InterceptAsync_AfterInvocation");
}
[Fact]
public async Task Should_Intercept_Async_Method_With_Return_Value()
{
//Arrange
var target = ServiceProvider.GetService<SimpleInterceptionTargetClass>();
//Act
var result = await target.GetValueAsync();
//Assert
result.ShouldBe(42);
target.Logs.Count.ShouldBe(9);
target.Logs[0].ShouldBe("SimpleAsyncInterceptor_InterceptAsync_BeforeInvocation");
target.Logs[1].ShouldBe("SimpleSyncInterceptor_Intercept_BeforeInvocation");
target.Logs[2].ShouldBe("SimpleAsyncInterceptor2_InterceptAsync_BeforeInvocation");
target.Logs[3].ShouldBe("EnterGetValueAsync");
target.Logs[4].ShouldBe("MiddleGetValueAsync");
target.Logs[5].ShouldBe("ExitGetValueAsync");
target.Logs[6].ShouldBe("SimpleAsyncInterceptor2_InterceptAsync_AfterInvocation");
target.Logs[7].ShouldBe("SimpleSyncInterceptor_Intercept_AfterInvocation");
target.Logs[8].ShouldBe("SimpleAsyncInterceptor_InterceptAsync_AfterInvocation");
}
[Fact]
public void Should_Intercept_Sync_Method_Without_Return_Value()
{
//Arrange
var target = ServiceProvider.GetService<SimpleInterceptionTargetClass>();
//Act
target.DoIt();
//Assert
target.Logs.Count.ShouldBe(7);
target.Logs[0].ShouldBe("SimpleAsyncInterceptor_Intercept_BeforeInvocation");
target.Logs[1].ShouldBe("SimpleSyncInterceptor_Intercept_BeforeInvocation");
target.Logs[2].ShouldBe("SimpleAsyncInterceptor2_Intercept_BeforeInvocation");
target.Logs[3].ShouldBe("ExecutingDoIt");
target.Logs[4].ShouldBe("SimpleAsyncInterceptor2_Intercept_AfterInvocation");
target.Logs[5].ShouldBe("SimpleSyncInterceptor_Intercept_AfterInvocation");
target.Logs[6].ShouldBe("SimpleAsyncInterceptor_Intercept_AfterInvocation");
}
[Fact]
public void Should_Intercept_Sync_Method_With_Return_Value()
{
//Arrange
var target = ServiceProvider.GetService<SimpleInterceptionTargetClass>();
//Act
var result = target.GetValue();
//Assert
result.ShouldBe(42);
target.Logs.Count.ShouldBe(7);
target.Logs[0].ShouldBe("SimpleAsyncInterceptor_Intercept_BeforeInvocation");
target.Logs[1].ShouldBe("SimpleSyncInterceptor_Intercept_BeforeInvocation");
target.Logs[2].ShouldBe("SimpleAsyncInterceptor2_Intercept_BeforeInvocation");
target.Logs[3].ShouldBe("ExecutingGetValue");
target.Logs[4].ShouldBe("SimpleAsyncInterceptor2_Intercept_AfterInvocation");
target.Logs[5].ShouldBe("SimpleSyncInterceptor_Intercept_AfterInvocation");
target.Logs[6].ShouldBe("SimpleAsyncInterceptor_Intercept_AfterInvocation");
}
}
}

@ -0,0 +1,26 @@
using System.Threading.Tasks;
using Volo.Abp.DynamicProxy;
using Volo.Abp.TestBase.Logging;
using Volo.DependencyInjection;
namespace Volo.Abp.Castle.DynamicProxy
{
public class SimpleAsyncInterceptor : AbpInterceptor, ITransientDependency
{
public override void Intercept(IAbpMethodInvocation invocation)
{
(invocation.TargetObject as ICanLogOnObject)?.Logs?.Add($"{GetType().Name}_Intercept_BeforeInvocation");
invocation.ProceedAsync();
(invocation.TargetObject as ICanLogOnObject)?.Logs?.Add($"{GetType().Name}_Intercept_AfterInvocation");
}
public override async Task InterceptAsync(IAbpMethodInvocation invocation)
{
//await Task.Delay(5); CAN NOT USE await before method execution! This is a restriction of Castle DynamicProxy
(invocation.TargetObject as ICanLogOnObject)?.Logs?.Add($"{GetType().Name}_InterceptAsync_BeforeInvocation");
await invocation.ProceedAsync();
(invocation.TargetObject as ICanLogOnObject)?.Logs?.Add($"{GetType().Name}_InterceptAsync_AfterInvocation");
await Task.Delay(5);
}
}
}

@ -0,0 +1,7 @@
namespace Volo.Abp.Castle.DynamicProxy
{
public class SimpleAsyncInterceptor2 : SimpleAsyncInterceptor
{
}
}

@ -1,31 +0,0 @@
using System.Threading.Tasks;
using Volo.Abp.DynamicProxy;
using Volo.Abp.TestBase.Logging;
using Volo.DependencyInjection;
namespace Volo.Abp.Castle.DynamicProxy
{
public class SimpleInterceptor : IAbpInterceptor, ITransientDependency
{
public async Task InterceptAsync(IAbpMethodInvocation invocation)
{
//await Task.Delay(5);
(invocation.TargetObject as ICanLogOnObject)?.Logs?.Add("SimpleInterceptor_BeforeInvocation");
await invocation.ProceedAsync();
(invocation.TargetObject as ICanLogOnObject)?.Logs?.Add("SimpleInterceptor_AfterInvocation");
await Task.Delay(5);
}
}
public class SimpleInterceptor2 : IAbpInterceptor, ITransientDependency
{
public async Task InterceptAsync(IAbpMethodInvocation invocation)
{
//await Task.Delay(5);
(invocation.TargetObject as ICanLogOnObject)?.Logs?.Add("SimpleInterceptor2_BeforeInvocation");
await invocation.ProceedAsync();
(invocation.TargetObject as ICanLogOnObject)?.Logs?.Add("SimpleInterceptor2_AfterInvocation");
await Task.Delay(5);
}
}
}

@ -0,0 +1,16 @@
using Volo.Abp.DynamicProxy;
using Volo.Abp.TestBase.Logging;
using Volo.DependencyInjection;
namespace Volo.Abp.Castle.DynamicProxy
{
public class SimpleSyncInterceptor : AbpInterceptor, ITransientDependency
{
public override void Intercept(IAbpMethodInvocation invocation)
{
(invocation.TargetObject as ICanLogOnObject)?.Logs?.Add($"{GetType().Name}_Intercept_BeforeInvocation");
invocation.Proceed();
(invocation.TargetObject as ICanLogOnObject)?.Logs?.Add($"{GetType().Name}_Intercept_AfterInvocation");
}
}
}
Loading…
Cancel
Save