Autofac + Interceptors(AOP) 動態代理

Autofac 是個IOC容器 不懂IOC 參考 我之前寫
IOC(控制反轉),DI(依賴注入) 深入淺出~~

小弟之前有一個開源框架 裡面簡單介紹 AOP核心概念和如何實作!

Autofac 有寫一個 Autofac.Extras.DynamicProxy 把AOP和IOC容器融合的框架

在Autofac使用AOP 需要實現下面幾個步驟

本次範例我們從資料庫中撈取時間資料出來,並使用Thread.Sleep(5000)作出延遲,判斷時間是否前後一致。

第一步(定義攔截器):

我們撰寫一個快取的攔截器繼承IInterceptor 介面,並實現Intercep方法

其中 IInvocation參數有許多有用的資料

  • Arguments:傳入方法中的參數
  • InvocationTarget :被代理物件
  • MethodInvocationTarget:被代理物件的呼叫方法資訊
  • Proxy:代理物件
  • Method:代理的呼叫方法資訊
  • ReturnValue:呼叫方法的回傳值

這幾個欄位是我們比較常用的資訊

public class TimeInterceptor : IInterceptor
{
    private ITimeService _timeService;
    public TimeInterceptor(ITimeService s)
    {

        _timeService = s;
    }

    public void Intercept(IInvocation invocation)
    {
        var time = CallContext.GetData("time")?.ToString();
        if (time == null)
        {
            //如果沒有快取 執行呼叫Service
            invocation.Proceed();
            CallContext.SetData("time", invocation.ReturnValue);
        }
        else
        {
            //如果有快取直接取值
            invocation.ReturnValue = time;
        }
    }
}

他使用到 TimeService 模擬從資料庫中撈取資料出來

public interface ITimeService
{
    string GetTime();
}

public class TimeService : ITimeService
{
    public string GetTime()
    {
        return DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss");
    }
}

第二步(標記攔截器):

使用Intercept標籤並帶入要攔截類別型態.

[Intercept(typeof(TimeInterceptor))]
public class Person : IPerson
{
    public string SaySomething()
    {
        return DateTime.Now.ToLongTimeString();
    }
}

public interface IPerson
{
    string SaySomething();
}

第三步(註冊攔截器到容器中):

這邊有兩個小細節

  1. 如果是註冊介面使用EnableInterfaceInterceptors,註冊一般類別使用EnableClassInterceptors
  2. 註冊攔截器入容器

因為這個範例使用所以我們要呼叫EnableInterfaceInterceptors

var builder = new ContainerBuilder();

builder.RegisterType<TimeInterceptor>(); //註冊攔截器

builder.RegisterType<Person>()
        .As<IPerson>()
        .EnableInterfaceInterceptors();

//註冊時間Service
builder.RegisterType<TimeService>().As<ITimeService>();

return builder.Build();

原始碼連結

小結

Autofac + DynamicProxy 有一個很大優勢,是可以把要注入的抽象動作一起注入攔截器中

例如本次範例我們將ITimeService使用建構子注入法,注入至TimeInterceptor攔截器中

讓系統和寫法擁有更多更多的彈性

此文作者:Daniel Shih(石頭)
此文地址https://isdaniel.github.io/autofac-aop/
版權聲明:本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 3.0 TW 許可協議。轉載請註明出處!


如果本文對您幫助很大,可街口支付斗內鼓勵石頭^^