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

截圖說明一下兩個框架的區別,到時候可根據框架需要酌情使用:

 

  有不足之處 希望大家指出相互學習,

                                     本文原創:轉載請注明出處 謝謝!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM