Skip to main content
 首页 » 编程设计

AspNetCore 基于AOP实现Polly的使用

2022年07月15日56落叶

前言  

说起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博客。

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

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

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


本文参考链接:https://www.cnblogs.com/szlblog/p/9425164.html