3rd Party — AspectInjector (C# AOP套件)

莊創偉
5 min readFeb 1, 2021

Nuget

github

AspectInjector 是一套開源的 AOP套件使用起來相當簡便而且支援 async await

AspectInjector 使用方法跟 ActionFilter 有點類似。先建立Attribute 之後在要套用的方法或類別上加上 tag。

首先安裝好AspectInjector

假設我們要建立一個負責寫Log的Class

[Aspect(Scope.Global)]
public class WriteLog
{
[Advice(Kind.Before, Targets = Target.Method)]
public void Before()
{
Console.WriteLine("Method Begin");
}
[Advice(Kind.After, Targets = Target.Method)]
public void After()
{
Console.WriteLine("Method After");
}
}

其中Aspect 是設定物件的生命週期,有 Glbal PerInstance兩種模式可以選擇 Global 表示物件將建立為singleton,反之為 Transient 隨攔截物件一同建立與消滅。

Adivce 定義進入點與攔截的目標。Kind Before、After、Around 三種屬性、Target 的有非常多列舉,一般常用應該都包在裡面了,如果要一次增加多組條件可以使用 | 串接 ex :Targets = Target.Method |Target.Public

簡單的定義好物件之後接下來就是建立攔截器

[Injection(typeof(WriteLog))]public class WriteLogAttribute : Attribute{}

Injection 表示要載入的 Aspect 物件。可以加載多個 Injection ,也可以加載自己。若加載多個Injection,則加載順序是由上而下、由內而外依序加載。

之後在要記錄 Log的目標上加上 tag就可以了

class Program{static void Main(string[] args)
{
DoSomething();
Console.ReadKey();
}
[WriteLog]
static void DoSomething()
{
Console.WriteLine("Work");
}
}

運行結果如下

另外 AspectInjector 可以透過 Argument 來取得攔截目標的入參等各種屬性。
假設我們要再加上計時器,計算耗費時間

[Aspect(Scope.Global)]
public class SpendTime
{
private Stopwatch _timer = new Stopwatch();
[Advice(Kind.Around, Targets = Target.Method)]
public object Around(
[Argument(Source.Arguments)] object[] arguments,[Argument(Source.Target)] Func<object[], object> target)
{
_timer.Start();
//Around 會截停目標方法,所以需自行執行然後返回結果,否則會出錯
var result = target(arguments);
_timer.Stop();Console.WriteLine("spend "+ _timer.ElapsedTicks);_timer.Reset();return result;
}
[Advice(Kind.Before, Targets = Target.Method)]
public void Before()
{
Console.WriteLine("Before SpendTime");
}
[Advice(Kind.After, Targets = Target.Method)]
public void After()
{
Console.WriteLine("After SpendTime");
}
}

完成後一樣加上Injection

[Injection(typeof(WriteLog))]
[Injection(typeof(SpendTime))]
public class WriteLogAttribute : Attribute{}

執行後結果如下

執行順序是由上而下由內而外

--

--

莊創偉

學海無涯。但是為了生計還是得下海的風塵男子