在asp.net mvc或asp.net miniapi中,有過濾器,可以在請求前或后增加一層,達到驗證,過濾等作用,如果在Service的方法前后加一層呢?這里介紹一下Castle.DynamicProxy的用法。
首先引入
Castle.Core
實現代碼相對輕量:
using Castle.DynamicProxy;
using Microsoft.Extensions.DependencyInjection.Extensions;var builder = WebApplication.CreateBuilder(args);
builder.Services.AddInterceptedSingleton<ITestService, TestService, AddLogInterceptor>();var app = builder.Build();app.MapGet("/test", (ITestService test) =>
{app.Logger.LogInformation("/test開始");var result = test.Get(121);app.Logger.LogInformation("/test結束");return result;
});app.Run();public interface ITestService
{string Get(int id);
}
public class TestService : ITestService
{private readonly ILogger<TestService> _logger;public TestService(ILogger<TestService> logger){_logger = logger;}public string Get(int id){_logger.LogInformation("TestService.Get({id})", id);return "OK";}
}
public class AddLogInterceptor : IInterceptor
{private readonly ILogger<AddLogInterceptor> _logger;public AddLogInterceptor(ILogger<AddLogInterceptor> logger){_logger = logger;}public void Intercept(IInvocation invocation){//用invocation可以獲取被調用對象和方法的信息_logger.LogInformation("開始調用{name},參數:{args}", invocation.Method.Name, string.Join(",", invocation.Arguments));invocation.Proceed();_logger.LogInformation("結束調用{name},返回結果:{result}", invocation.Method.Name, invocation.ReturnValue);}
}
public static class InterceptedExpansion
{public static void AddInterceptedSingleton<TIService, TService, TInterceptor>(this IServiceCollection services)where TIService : classwhere TService : class, TIServicewhere TInterceptor : class, IInterceptor{services.TryAddSingleton<IProxyGenerator, ProxyGenerator>();services.AddSingleton<TService>();services.TryAddTransient<TInterceptor>();services.AddSingleton(provider =>{var proxyGenerator = provider.GetRequiredService<IProxyGenerator>();var service = provider.GetRequiredService<TService>();var interceptor = provider.GetRequiredService<TInterceptor>();return proxyGenerator.CreateInterfaceProxyWithTarget<TIService>(service, interceptor);});}
}
效果如下: