• AspNetCore 基于AOP实现Polly的使用


    前言  

    说起AOP,其实我们在做MVC/API 的时候应该没少接触,比如说各种的Fitter 就是典型的AOP了。

    本来在使用Polly的时候我最初的打算是使用过滤器来实现的,后来发现实现起来相当的困难,利用NetCore的中间以及过滤器去实现一个AOP的独立应用服务简直了,我有点无奈,相当的难写。

    后来又使用了,Autofac 做拦截器来实现也是有点小无力。估计还是基础太薄弱。

    目前我了解到的实现Polly比较方便的第三方Aop框架的有

    (1)AspectCore:是一款 AspNetCore轻量级的Aop解决方案。

    (2)Dora.Interception 老A写的一个Aop解决方案,这个用到解决方案中就需要等到老A升级下一版了。

     

      AspNetCore中的过滤器

    在使用Policy 的时候主要点是策略的制定,在保证代码整洁,并且不破坏当前代码逻辑的情况下,使用Aop是最合适的解决方案了。

    当我们使用过滤器的时候我们会发现,Pollicy 制定了一个错误规则,并且在错误过滤器中使用、抓取不到任何的错误信息,因为错误信息被错误过滤器抓取了,这个时候不会触发Pollicy

     

    然后尝试着 用过滤实现一个 当程序发生错误的时候,执行另一个方法的功能,类似Policy的重试策略或降级。

    下面代码:

    编写:一个过滤器类:

     

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.Filters;
    using System;
    using System.Reflection;
    
    
    namespace InterceptorCoreLibrary
    {
        [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method)]
        public class CoreExceptionFilter:Attribute, IExceptionFilter,IActionFilter
        {
            /// <summary>
            /// 发生错误的时候重新执行的方法
            /// </summary>
            public string FallBackClass { get; set; }
            /// <summary>
            /// 发生错误的时候重新执行的方法
            /// </summary>
            public string FallBackMethod { get; set; }
    
            /// <summary>
            /// 获取方法的参数
            /// </summary>
            public object[] InvokeParameters { get; set; }
    
            /// <summary>
            /// 构造函数使用该类时参数为方法
            /// </summary>
            /// <param name="fallBackMethod"></param>
            public CoreExceptionFilter(string fallBackClass, string fallBackMethod) 
            {
                this.FallBackMethod = fallBackMethod;
                this.FallBackClass = fallBackClass;
            }
            /// <summary>
            /// 使用新方法
            /// </summary>
            /// <param name="asm"></param>
            /// <param name="parameters"></param>
            /// <returns></returns>
            private object UseNewMethod(Assembly asm, object[] parameters)
            {
                Object obj = null;
                foreach (Type type in asm.GetExportedTypes())
                {
                    if (type.Name == FallBackClass)
                    {
                        obj = System.Activator.CreateInstance(type);
                        foreach (var item in type.GetMethods())
                        {
                            if (item.Name == FallBackMethod)
                            {
                                obj = type.GetMethod(FallBackMethod).Invoke(obj, parameters);
                            }
                        }
                    }
                }
                return obj;
            }
            /// <summary>
            /// 获取所有被监控方法的参数
            /// </summary>
            /// <param name="context"></param>
            public void OnActionExecuting(ActionExecutingContext context)
            {
                object[] parameters = new object[context.ActionArguments.Count];
                int Count = 0;
                foreach (var item in context.ActionArguments)
                {
                    parameters[Count] = item.Value;
                    Count++;
                }
                InvokeParameters = parameters;
            }
    
            /// <summary>
            /// 错误的时候执行新的方法
            /// </summary>
            /// <param name="context"></param>
            public void OnException(ExceptionContext context)
            {
                var objectResult = context.Exception as Exception;
                if (objectResult.Message != null)
                {
                    //context.Result = new ObjectResult(UseNewMethod(this.GetType().Assembly, InvokeParameters));
                     context.Result = new ObjectResult(new { Success = true, code = 200, msg = "成功", Data = UseNewMethod(this.GetType().Assembly, InvokeParameters) });
                }
            }
            public void OnActionExecuted(ActionExecutedContext context)
            {
               
            }
        }
    }

     

    在控制器中使用:

     

     [CoreExceptionFilter(nameof(UserModel), nameof(Delete))]
    
     
    
       在执行的时候我抛送一个异常信息
    
        [CoreExceptionFilter(nameof(UserModel), nameof(Delete))]
    
            // DELETE api/values/5
    
            [HttpDelete("{id}")]
    
            public int Delete(int id)
    
            {
    
                throw new Exception();
    
            }

    当方法执行出错的时候执行另一个方法:

    如下:注意参数一致:

    using System;
    using System.Collections.Generic;
    using System.Text;
    
    namespace InterceptorCoreLibrary
    {
        public class UserModel
        {
            public int   Delete(int id)
            {
                //记录日志
                //重新执行一遍代码
                return id;
            }
        }
    }

    执行结果:

     

    返回结果:

     

    这个时候我们能看到过滤器先抓取了错误信息,Policy 就抓不到了,但同样实现了降级的功能。

    如果我们不使用Aop的话 直接在控制器中写

    比如:这样写一个两个还行多了的话,代码就相当的乱了。

     // DELETE api/values/5
            [HttpDelete("{id}")]
            public int Delete(int id)
            {
                var PolicyExecute = Policy.Handle<Exception>().Fallback(() =>
                  {
                      //程序报错重新执行一个新的方法
                      UserModel userModel = new UserModel();
                      userModel.Delete(id);
                 });
                
                //执行
                 PolicyExecute.Execute(() =>            {
                                    throw new Exception();
                                }
                               );
            }

    以上代码虽然没有实现policy ,但是也演示出了大致使用Aop实现 Policy的过程原理。

    使用AspectCore 实现Policy

    这里贴出一份杨中科老师 在普及AspNetCore微服务课程中的代码:支持原创,

    完整的代码这里贴出过:

    http://www.cnblogs.com/qhbm/p/9228238.html

    使用Dora.Interception 实现Policy

    我在Demo中进行了简单的实现:这里就不贴出了,因为框架还不是很完善,我问了作者老A,要等到下一版出来后用在项目中才比较稳妥。大家可以关注一下老A博客。

    截图说明一下两个框架的区别,到时候可根据框架需要酌情使用:

      有不足之处 希望大家指出相互学习,

                                         本文原创:转载请注明出处 谢谢!

  • 相关阅读:
    [Canvas]RPG游戏雏形 (地图加载,英雄出现并移动)
    [Canvas]计时表/秒表
    [Canvas]新版箴言钟表
    [Canvas]用透明PNG图在背景上画前景能不遮挡背景
    [Canvas]动态背景
    [Canvas]更多的球
    [Canvas]碰撞球 增加小球间碰撞检测
    [Canvas]碰撞球
    [Canvas]越来越近的女孩
    [Canvas]走近的女孩
  • 原文地址:https://www.cnblogs.com/szlblog/p/9425164.html
Copyright © 2020-2023  润新知