码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • aspnetcore中aop的实现


    aaspnetcore开发框架中实现aop不仅仅在业务上,在代码的优雅简洁和架构的稳定上都有着至关重要。

    下面介绍三种用过的。

     

    第一种通过System.Reflection的DispatchProxy类来实现

    首先新建一个aspnetcore项目

     

    针对业务代码WarService加了一个代理的方法

    复制代码
    public interface IWarService
        {
            string WipeOut();
            IWarService Proxy(IWarService warService);
        }
    
    
     public class WarService : IWarService
        {
            public IWarService Proxy(IWarService warService)
            {
                return WarDispatch.Create(warService);
            }
    
            public string WipeOut()
            {
                return "us is over";
            }
        }
    复制代码

    具体的WarDispatch就是核心代码了,继承自DispatchProxy。这里的before和after的实现就是针对实现了代码的service提前挖坑。

    复制代码
    public class WarDispatch : DispatchProxy where T : class
        {
            private T Target { get; set; }
            public static T Create(T target) where T : class
            {
                var proxy = Create>() as WarDispatch;
                proxy.Target = target;
                return proxy as T;
            }
    
            protected override object? Invoke(MethodInfo? targetMethod, object?[]? args)
            {
                Before().Wait();
                var result = targetMethod.Invoke(Target, args);
                After().Wait();
                return result;
            }
    
            Task Before()
            {
                return Task.CompletedTask;
            }
    
            Task After()
            {
                return Task.CompletedTask;
            }
        }
    复制代码

    实现代码也相当简单

    复制代码
    [ApiController]
        [Route("[controller]")]
        public class RescueEarthController : ControllerBase
        {
            private IWarService _warService;
            
            public RescueEarthController(IWarService warService)
            {
                _warService = warService;
            }
    
            [HttpGet(Name = "AnnihilateHegemony")]
            public string AnnihilateHegemony()
            {
                var proxy = _warService.Proxy(_warService); //代理
                return proxy.WipeOut();
            }
    
            [HttpGet("two")]
            public string AnnihilateHegemonyTwo()
            {
                return _warService.WipeOut();
            }
        }
    复制代码

    当然不要忘了注入下服务类

    builder.Services.AddScoped();

    上面的方式是我自己想出来的,具体到项目中需要改进的地方应该还有很多,但是足够简单,功能也比较单一。

     

    下面简单介绍下AspectCore.DynamicProxy现成组件的代理使用。

    首先引用aspnetcore.extensions.dependencyinjection包

    在program中使用动态代码

    复制代码
     builder.Host.UseServiceProviderFactory(new DynamicProxyServiceProviderFactory());
                builder.Services.ConfigureDynamicProxy(o =>{ 
                //添加aop的配置
                //该项目用attribute所以无需配置
               
                });
    复制代码

    内存的缓存代理

    复制代码
     public class CacheDeleteInterceptorAttribute:AbstractInterceptorAttribute
        {
            private readonly Type[] _types;
            private readonly string[] _methods;
            public CacheDeleteInterceptorAttribute(Type[] types, string[] methods)
            {
                if (types.Length != methods.Length)
                {
                    throw new Exception("Types必须跟Methods数量一致");
                }
                _types = types;
                _methods = methods;
            }
    
            public override async Task Invoke(AspectContext context, AspectDelegate next)
            {
                var cache = context.ServiceProvider.GetService();
                await next(context);
                for (int i = 0; i < _types.Length; i++)
                {
                    var type = _types[i];
                    var method = _methods[i];
                    string key = "Methods:" + type.FullName + "." + method;
                    cache.Remove(key);
                }
            }
        }
    复制代码
    复制代码
     public class CacheInterceptorAttribute : AbstractInterceptorAttribute
        {
            public override async Task Invoke(AspectContext context, AspectDelegate next)
            {
                bool isAsync = context.IsAsync();
                var methodReturnType = context.GetReturnParameter().Type;
                if(methodReturnType==typeof(void)|| methodReturnType==typeof(Task) || methodReturnType == typeof(ValueTask))
                {
                    await next(context);
                    return;
                }
                var returnType = methodReturnType;
                if (isAsync)
                {
                    returnType = returnType.GenericTypeArguments.FirstOrDefault();
                }
                //string param = GetParaName(context.Parameters); //获取方法的参数名,
                string key = $"Methods:{context.ImplementationMethod.DeclaringType.FullName}.{context.ImplementationMethod.Name}";//获取方法名称,也就是缓存key值
                var cache = context.ServiceProvider.GetService(); //可以使用自定义的redis或者其他缓存
                if (cache.Get(key) != null)
                {
                    //反射获取缓存值
                    var value = typeof(MemoryCache).GetMethod("MemoryCache.Get").MakeGenericMethod(returnType).Invoke(cache, new[] {
                        key
                        //, param 
                    });
                    if (isAsync)
                    {
    
                        //判断是Task还是ValueTask
                        if (methodReturnType == typeof(Task<>).MakeGenericType(returnType))
                        {
                            //反射获取Task<>类型的返回值,相当于Task.FromResult(value)
                            context.ReturnValue = typeof(Task).GetMethod(nameof(Task.FromResult)).MakeGenericMethod(returnType).Invoke(null, new[] { value });
                        }
                        else if (methodReturnType == typeof(ValueTask<>).MakeGenericType(returnType))
                        {
                            //反射构建ValueTask<>类型的返回值,相当于new ValueTask(value)
                            context.ReturnValue = Activator.CreateInstance(typeof(ValueTask<>).MakeGenericType(returnType), value);
                        }
                    }
                    else
                    {
                        context.ReturnValue = value;
                    }
                    return;
                }
                await next(context);
                object returnValue;
                if (isAsync)
                {
                    returnValue = await context.UnwrapAsyncReturnValue();
                    //反射获取异步结果的值,相当于(context.ReturnValue as Task<>).Result
                    //returnValue = typeof(Task<>).MakeGenericType(returnType).GetProperty(nameof(Task.Result)).GetValue(context.ReturnValue);
    
                }
                else
                {
                    returnValue = context.ReturnValue;
                }
                cache.Set(key
                    //, param
                    , returnValue);
                if(ExpireSeconds > 0)
                {
                    cache.Set(key, TimeSpan.FromSeconds(ExpireSeconds));//设置key的过期时间
                }
            }
    
            //private string GetParaName(object[] parameters)
            //{
            //    throw new NotImplementedException();
            //}
    
            /// 
            /// 缓存秒数
            /// 
            public int ExpireSeconds { get; set; }
        }
    
    复制代码

    dbcontext的代理

    复制代码
    public class TransactionInterceptorAttribute : AbstractInterceptorAttribute
        {
            //public override async Task Invoke(AspectContext context, AspectDelegate next)
            //{
            //    var dbcontext = context.ServiceProvider.GetService();
            //    if (dbcontext.Database.CurrentTransaction != null)
            //    {
            //        await dbcontext.Database.BeginTransactionAsync();
            //        try
            //        {
            //            await next(context);
            //            await dbcontext.Database.CommitTransactionAsync();
            //        }catch(Exception ex)
            //        {
            //           await dbcontext.Database.RollbackTransactionAsync();
            //            throw ex;
            //        }
            //    }
            //    else
            //    {
            //        await next(context);
            //    }
            //}//一个context
    
            public override async Task Invoke(AspectContext context, AspectDelegate next)
            {
                var dbcontext = context.ServiceProvider.GetService();
                var dbcontextNext = context.ServiceProvider.GetService();
                var transactionManager = dbcontext.Database.GetService();
                var transaction = await transactionManager.BeginTransactionAsync();
    
                if (transaction != null)
                {
                    await dbcontext.Database.BeginTransactionAsync();
                    try
                    {
                        await next(context);
                        await transaction.CommitAsync();
                    }
                    catch (Exception ex)
                    {
                        await transaction.RollbackAsync();
                        throw ex;
                    }
                }
                else
                {
                    await next(context);
                }
            }//多个context
        }
    复制代码
    复制代码
     public class CommonDbContext:DbContext
        {
            public CommonDbContext(DbContextOptions options):base(options)
            {
    
            }
        }
    
        public class NextDbContext : DbContext
        {
            public NextDbContext(DbContextOptions options) : base(options)
            {
    
            }
        }
    复制代码

    使用就是这么简单

    复制代码
     public class TestOperatorDbBusiness
        {
            [TransactionInterceptor]
            public async ValueTask Add()
            {
                //TODO事务操作
            }
        }
    复制代码

     

    上面的代理组件功能非常多,项目中需要自己去研究更多更全的用法。

    上面代码的demo

    exercisebook/AOP at main · liuzhixin405/exercisebook (github.com)

    还有Castle.DynamicProxy,这个比较复杂一点。具体用法给个实例demo

    exercisebook/AspNetCoreAOP at main · liuzhixin405/exercisebook (github.com)

    总结:

    一个aspnetcore中需要用到aop的地方非常多,框架自带的中间件,filter过滤器,efcore自带Interceptor都可以拿来用。

    中间件例如mediator,这里面的拦截器也非常多,还有好多等待发掘。

    当然自己也可以定义一些简单的中间层来做拦截。

    相信多了解 在框架中有需要用的地方会事半功倍。

    最后附上自己写的超级简单的aop组件,没有引用任何第三方组件,当然功能方面有待丰富,有兴趣的伙伴可以帮忙改进改善。

    liuzhixin405/AspNetCoreSimpleAop (github.com)

     

  • 相关阅读:
    全球最受欢迎的「数字游民」城市竟然是它?
    竞赛选题 深度学习 python opencv 火焰检测识别
    SRV1:拥有一个阿里云服务器
    06-引入Express创建web服务器、接口封装并使用postman测试,静态资源托管
    IDEFICS 简介: 最先进视觉语言模型的开源复现
    测试人生 | 从功能到外企测开,工作1年半拿下年薪30万的测开 offer,这个95后小姐姐未来可期~
    C++ Reference: Standard C++ Library reference: C Library: cuchar: mbrtoc16
    【数智化人物展】同方有云联合创始人兼总经理江琦:云计算,引领数智化升级的动能...
    “碳中和”愿景下,什么样的数据中心才是我们需要的?
    基于聚类算法:K-means、DBSCA算法完成航空客户价值分析任务 代码+数据
  • 原文地址:https://www.cnblogs.com/morec/p/17249940.html
    • 最新文章
    • 攻防演习之三天拿下官网站群
      数据安全治理学习——前期安全规划和安全管理体系建设
      企业安全 | 企业内一次钓鱼演练准备过程
      内网渗透测试 | Kerberos协议及其部分攻击手法
      0day的产生 | 不懂代码的"代码审计"
      安装scrcpy-client模块av模块异常,环境问题解决方案
      leetcode hot100【LeetCode 279. 完全平方数】java实现
      OpenWrt下安装Mosquitto
      AnatoMask论文汇总
      【AI日记】24.11.01 LangChain、openai api和github copilot
    • 热门文章
    • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
      奉劝各位学弟学妹们,该打造你的技术影响力了!
      五年了,我在 CSDN 的两个一百万。
      Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
      面试官都震惊,你这网络基础可以啊!
      你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
      心情不好的时候,用 Python 画棵樱花树送给自己吧
      通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
      13 万字 C 语言从入门到精通保姆级教程2021 年版
      10行代码集2000张美女图,Python爬虫120例,再上征途
    Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
    正则表达式工具 cron表达式工具 密码生成工具

    京公网安备 11010502049817号