1. 程式人生 > 實用技巧 >【ASP.NET Core 3.1_參考中介軟體原始碼實現自定義AOP】

【ASP.NET Core 3.1_參考中介軟體原始碼實現自定義AOP】

一、參考中介軟體原始碼實現自定義AOP 場景:在真實執行邏輯學習這個方法包一層層(學習前吃點東西、上個廁所),模擬中介軟體,一層層穿過 思路:物件構造完,加1個動態代理,基於Castle、組裝委託,來個AOP擴充套件,像一個俄羅斯套娃
二、AOP擴充套件方法--ContainerAOPExtensions.cs 2.1、Nuget引入Castle.Core.dll 2.2、實現擴充套件方法,目的把服務包一層代理
/// <summary>
/// 自定義AOP擴充套件
/// </summary>
public static class ContainerAOPExtensions
{
    
/// <summary> /// /// </summary> /// <param name="t">物件</param> /// <param name="interfaceType">介面型別</param> /// <returns></returns> public static object AOP(this object t, Type interfaceType) { ProxyGenerator generator = new ProxyGenerator(); ProxyInterceptor interceptor
= new ProxyInterceptor(); t = generator.CreateInterfaceProxyWithTarget(interfaceType, t, interceptor); return t; } }

三、自定義攔截屬性 3.1、基類
public abstract class BaseInterceptorAttribute : Attribute
{
    public abstract Action Do(IInvocation invocation, Action action);
}

3.2、吃點東西攔截屬性
/// <summary>
/// 學習前吃點東西
/// </summary>
public class EatInterceptorAttribute : BaseInterceptorAttribute
{
    public override Action Do(IInvocation invocation, Action action)
    {
        return () =>
        {
            Console.WriteLine($"This is Eat1 {invocation.Method.Name} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}");

            //去執行真實邏輯
            action.Invoke();

            Console.WriteLine($"This is Eat2 {invocation.Method.Name} {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}");
        };
    }
}

3.3、上個廁所攔截屬性
/// <summary>
/// 學習前上個廁所
/// </summary>
public class GoToiletInterceptorAttribute : BaseInterceptorAttribute
{
    public override Action Do(IInvocation invocation, Action action)
    {
        return () =>
        {
            Console.WriteLine($"This is GoToilet1  {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}");

            //去執行真實邏輯
            action.Invoke();

            Console.WriteLine($"This is GoToilet2  {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}");
        };
    }
}

四、攔截器--ProxyInterceptor.cs
/// <summary>
/// 攔截器
/// </summary>
public class ProxyInterceptor : StandardInterceptor
{
    /// <summary>
    /// 呼叫前的攔截器
    /// </summary>
    /// <param name="invocation"></param>
    protected override void PreProceed(IInvocation invocation)
    {
        Console.WriteLine($"呼叫前的攔截器 方法名是:{invocation.Method.Name}  {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}");
    }

    /// <summary>
    /// 攔截的方法返回時呼叫的攔截器
    /// </summary>
    /// <param name="invocation"></param>
    protected override void PerformProceed(IInvocation invocation)
    {
        var method = invocation.Method;
        //真實邏輯包成委託--Study()--對應學生服務裡的‘我要學習了’
        Action action = () => base.PerformProceed(invocation);

        
        if (method.IsDefined(typeof(BaseInterceptorAttribute), true))
        {
            foreach (var attribute in method.GetCustomAttributes<BaseInterceptorAttribute>().ToArray().Reverse())
            {
                //組裝、再組裝委託
                action = attribute.Do(invocation, action);
            }
        }
        //最後一次性執行委託
        action.Invoke();
    }

    /// <summary>
    /// 呼叫後的攔截器
    /// </summary>
    /// <param name="invocation"></param>
    protected override void PostProceed(IInvocation invocation)
    {
        Console.WriteLine($"呼叫後的攔截器 方法名是:{invocation.Method.Name}  {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff")}");
    }
}

五、學生介面、學生服務 5.1、IStudentService.cs 在介面上面加上自定義攔截屬性
/// <summary>
/// 學生介面
/// </summary>
public interface IStudentService 
{
    /// <summary>
    /// 學習
    /// </summary>
    [EatInterceptor]
    [GoToiletInterceptor]
    public void Study();
}

5.2、StudentService.cs

Study()是真實邏輯
/// <summary>
/// 學生服務
/// </summary>
public class StudentService : IStudentService
{
    /// <summary>
    /// 學習
    /// </summary>
    public void Study()
    {
        Console.WriteLine("我要學習了!");
    }
}
六、上端呼叫
public class TestCustomAOPController : Controller
{
    //學生服務介面
    private IStudentService _iStudentService = null;

    public TestCustomAOPController(IStudentService iStudentService)
    {
        _iStudentService = iStudentService;
    }
public IActionResult Index() { Console.WriteLine("******************普通方法呼叫*********************"); _iStudentService.Study(); Console.WriteLine("*******************AOP擴充套件後********************"); _iStudentService = (IStudentService)_iStudentService.AOP(typeof(IStudentService)); _iStudentService.Study(); return View(); } }

七、專案結構 八、執行效果 總結:把真實邏輯Study()方法先不執行,先包成委託傳入GoToiletGoToilet裡面對委託組裝後返回一個委託,再次把返回的委託再次傳入EatEat裡面對委託再次組裝後再返回一個委託,最後一次性執行委託 委託傳遞,組裝、再組裝、最後一次性執行委託,這其實就是我對ASP.NET Core Middleware中介軟體的理解 Castle、組裝委託,