AspectCore是適用於Asp.Net Core 平臺的輕量級Aop(Aspect-oriented programming)解決方案,它更好的遵循Asp.Net Core的模塊化開發理念,使用AspectCore能夠更容易構建低耦合、易擴展的Web應用程序。git
在使用過程當中,因爲相關文檔、博客還未更新到.Net Core 3.0,本文操做參考了使用.Net Core 3.0的EasyCaching,並對其中公用的方法進行封裝簡化。github
此處配合微軟自家的DI實現,安裝Nuget包AspectCore.Extensions.DependencyInjection,其中包含AspectCore.Core和Microsoft.Extensions.DependencyInjection兩個依賴。web
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.建立AspectCoreEctensions.cs擴展IServiceCollectionshell
public static class AspectCoreExtensions { public static void ConfigAspectCore(this IServiceCollection services) { services.ConfigureDynamicProxy(config => { //TestInterceptor攔截器類 //攔截代理全部Service結尾的類 config.Interceptors.AddTyped<TestInterceptor>(Predicates.ForService("*Service")); }); services.BuildAspectInjectorProvider(); } }
2.在Startup.cs中註冊服務c#
public void ConfigureServices(IServiceCollection services) { services.ConfigAspectCore(); }
3.在Program.cs中替換ServiceProviderFactoryasp.net
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() { //業務代碼 } }
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>類型結果 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; } }