AspectCore是適用于Asp.Net Core 平臺的輕量級Aop(Aspect-oriented programming)解決方案,它更好的遵循Asp.Net Core的模塊化開發(fā)理念,使用AspectCore可以更容易構建低耦合、易擴展的Web應用程序。
在使用過程中,由于相關文檔、博客還未更新到.Net Core 3.0,本文操作參考了使用.Net Core 3.0的EasyCaching,并對其中公用的方法進行封裝簡化。
此處配合微軟自家的DI實現(xiàn),安裝Nuget包AspectCore.Extensions.DependencyInjection,其中包含AspectCore.Core和Microsoft.Extensions.DependencyInjection兩個依賴。
Install-Package AspectCore.Extensions.DependencyInjection -Version 1.3.0
public class TestInterceptorAttribute : AbstractInterceptorAttribute{ public override Task Invoke(AspectContext context, AspectDelegate next) { return context.Invoke(next); }}
public class TestInterceptor : AbstractInterceptor{ public override Task Invoke(AspectContext context, AspectDelegate next) { return context.Invoke(next); }}
以下注冊方式僅適用于asp.net core 3.0(目前只到3.0),已知在2.2版本中,需要在ConfigureServices方法中返回IServiceProvider,并且program.cs中也不再需要替換ServiceProviderFactory。
1.創(chuàng)建AspectCoreEctensions.cs擴展IServiceCollection
public static class AspectCoreExtensions{ public static void ConfigAspectCore(this IServiceCollection services) { services.ConfigureDynamicProxy(config => { //TestInterceptor攔截器類 //攔截代理所有Service結(jié)尾的類 config.Interceptors.AddTyped<TestInterceptor>(Predicates.ForService("*Service")); }); services.BuildAspectInjectorProvider(); }}
2.在Startup.cs中注冊服務
public void ConfigureServices(IServiceCollection services){ services.ConfigAspectCore();}
3.在Program.cs中替換ServiceProviderFactory
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }).UseServiceProviderFactory(new AspectCoreServiceProviderFactory());
public interface ITestService{ [TestInterceptor] void Test();}
public class TestService{ [TestInterceptor] public virtual void Test() { //業(yè)務代碼 }}
private async Task<object> RunAndGetReturn(){ await Context.Invoke(Next); return Context.IsAsync() ? await Context.UnwrapAsyncReturnValue() : Context.ReturnValue;}
[FromContainer]private RedisClient RedisClient { get; set; }
private static readonly ConcurrentDictionary<MethodInfo, object[]> MethodAttributes = new ConcurrentDictionary<MethodInfo, object[]>();public static T GetAttribute<T>(this AspectContext context) where T : Attribute{ MethodInfo method = context.ServiceMethod; var attributes = MethodAttributes.GetOrAdd(method, method.GetCustomAttributes(true)); var attribute = attributes.FirstOrDefault(x => typeof(T).IsAssignableFrom(x.GetType())); if (attribute is T) { return (T)attribute; } return null;}
public static Type GetReturnType(this AspectContext context){ return context.IsAsync() ? context.ServiceMethod.ReturnType.GetGenericArguments()First() : context.ServiceMethod.ReturnType;}
private static readonly ConcurrentDictionary<Type, MethodInfo> TypeofTaskResultMethod = new ConcurrentDictionary<Type, MethodInfo>();public object ResultFactory(this AspectContext context,object result){ var returnType = context.GetReturnType(); //異步方法返回Task<T>類型結(jié)果 if (context.IsAsync()) { return TypeofTaskResultMethod .GetOrAdd(returnType, t => typeof(Task) .GetMethods() .First(p => p.Name == "FromResult" && p.ContainsGenericParameters) .MakeGenericMethod(returnType)) .Invoke(null, new object[] { result }); } else { return result; }}