From 892b32c303edf874870e7c69322316cea206414a Mon Sep 17 00:00:00 2001 From: maliming Date: Thu, 4 Sep 2025 15:56:09 +0800 Subject: [PATCH] Update interceptor docs with async usage and code fixes --- .../framework/infrastructure/interceptors.md | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/docs/en/framework/infrastructure/interceptors.md b/docs/en/framework/infrastructure/interceptors.md index d2f0541411..d50de3ad84 100644 --- a/docs/en/framework/infrastructure/interceptors.md +++ b/docs/en/framework/infrastructure/interceptors.md @@ -81,14 +81,14 @@ public class ExecutionTimeLogInterceptor : AbpInterceptor, ITransientDependency { var sw = Stopwatch.StartNew(); - _logger.LogInformation("Executing {invocation.TargetObject.GetType().Name}.{invocation.Method.Name}"); + _logger.LogInformation($"Executing {invocation.TargetObject.GetType().Name}.{invocation.Method.Name}"); // Proceed to the actual target method await invocation.ProceedAsync(); sw.Stop(); - _logger.LogInformation("Executed {invocation.TargetObject.GetType().Name}.{invocation.Method.Name} in {sw.ElapsedMilliseconds} ms"); + _logger.LogInformation($"Executed {invocation.TargetObject.GetType().Name}.{invocation.Method.Name} in {sw.ElapsedMilliseconds} ms"); } } ```` @@ -108,6 +108,21 @@ public interface IExecutionTimeLogEnabled } ```` +````csharp +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +// A simple service that added to the DI container and will be intercepted since it implements the `IExecutionTimeLogEnabled` interface +public class SampleExecutionTimeService : IExecutionTimeLogEnabled, ITransientDependency +{ + public virtual async Task DoWorkAsync() + { + // Simulate a long-running task to test the interceptor + await Task.Delay(1000); + } +} +```` + ````csharp using System; using Volo.Abp.DependencyInjection; @@ -133,18 +148,22 @@ public static class ExecutionTimeLogInterceptorRegistrar ````csharp public override void PreConfigureServices(ServiceConfigurationContext context) { - context.Services.OnRegistered(ExecutionTimeLogInterceptor.RegisterIfNeeded); + context.Services.OnRegistered(ExecutionTimeLogInterceptorRegistrar.RegisterIfNeeded); } ```` ## Restrictions and Important Notes +### Always use asynchronous methods + +For best performance and reliability, implement your service methods as asynchronous to avoid **async over sync**, that can cause unexpected problems, For more information, see [Should I expose synchronous wrappers for asynchronous methods?](https://devblogs.microsoft.com/dotnet/should-i-expose-synchronous-wrappers-for-asynchronous-methods/) + ### Virtual Methods Requirement For **class proxies**, methods need to be marked as `virtual` so that they can be overridden by the proxy. Otherwise, interception will not occur. ````csharp -public class MyService : ITransientDependency +public class MyService : IExecutionTimeLogEnabled, ITransientDependency { // This method CANNOT be intercepted (not virtual) public void CannotBeIntercepted() @@ -190,5 +209,5 @@ To avoid generating dynamic proxies for specific types, use the static class `Dy * [Video tutorial: Interceptors in ABP Framework](https://abp.io/video-courses/essentials/interception) * [Castle DynamicProxy](https://www.castleproject.org/projects/dynamicproxy/) -* [Castle.Core.AsyncInterceptor](https://github.com/JSkimming/Castle.Core.AsyncInterceptors) +* [Castle.Core.AsyncInterceptor](https://github.com/JSkimming/Castle.Core.AsyncInterceptor) * [ASP.NET Core Filters](https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters)