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; } }