var builder = new ContainerBuilder(); builder.RegisterType<SomeType>() .As<ISomeInterface>() .EnableInterfaceInterceptors(); builder.Register(c => new CallLogger(Console.Out)); var container = builder.Build(); var willBeIntercepted = container.Resolve<ISomeInterface>();
var builder = new ContainerBuilder(); builder.RegisterType<First>() .EnableClassInterceptors(); builder.Register(c => new CallLogger(Console.Out));
var cb = new ContainerBuilder(); cb.RegisterType<TestServiceInterceptor>(); cb.Register(c => CreateChannelFactory()).SingleInstance(); cb.Register(c => c.Resolve<ChannelFactory<ITestService>>().CreateChannel()) .InterceptTransparentProxy(typeof(IClientChannel)) .InterceptedBy(typeof(TestServiceInterceptor)) .UseWcfSafeRelease();
實戰一下
先看看基於接口的攔截器:
我們先定義一個借口,名為 ICalculater:

using Autofac.Extras.DynamicProxy2; namespace AOP.Interceptors { //[Intercept(typeof(CalculaterInterceptor))] public interface ICalculater { int Add(int x, int y); int Sub(int x, int y); } }
然后定義該接口的實現類 Calculater:

using Autofac.Extras.DynamicProxy2; namespace AOP.Interceptors { //[Intercept(typeof(CalculaterInterceptor))] public class Calculater : ICalculater { public int Add(int x, int y) { return x + y; } public int Sub(int x, int y) { return x - y; } } }
接下來,我們來定義攔截器。這里我們定義了兩個連接器,通過這兩個攔截器,我們將能很清晰的看到攔截器是如何工作的。
定義第一個攔截器 CalculaterInterceptor :

using System; using Castle.DynamicProxy; namespace AOP.Interceptors { public class CalculaterInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { // 在下個攔截器或目前方法處理之前處理 var args = invocation.Arguments; Console.WriteLine($"Before: x={args[0]}, y={args[1]}"); Console.WriteLine($"Before: Method={invocation.Method.Name}"); invocation.SetArgumentValue(0, 5); // handle invocation.Proceed(); // 調用下一個攔截器,直到最終的目標方法。 // Post Console.WriteLine($"After: TargetType={invocation.TargetType}"); Console.WriteLine($"After: ReturnValue={invocation.ReturnValue}"); invocation.ReturnValue = (int)invocation.ReturnValue - 2; } } }
定義第二個攔截器 CalculaterInterceptor2 :

using System; using Castle.DynamicProxy; namespace AOP.Interceptors { public class CalculaterInterceptor2 : IInterceptor { public void Intercept(IInvocation invocation) { var args = invocation.Arguments; Console.WriteLine($"Before2: x={args[0]}, y={args[1]}"); Console.WriteLine($"Before2: Method={invocation.Method.Name}"); invocation.Proceed(); Console.WriteLine($"After2: TargetType={invocation.TargetType}"); Console.WriteLine($"After2: ReturnValue={invocation.ReturnValue}"); invocation.ReturnValue = (int)invocation.ReturnValue - 1; // 將結果值減去 2 } } }
在 控制台 Main 函數輸入我們的結果:

static void Main(string[] args) { var builder = new ContainerBuilder(); builder.RegisterType<Calculater>() .As<ICalculater>() .EnableInterfaceInterceptors() .InterceptedBy(typeof(CalculaterInterceptor), typeof(CalculaterInterceptor2)); // 這里定義了兩個攔截器,注意它們的順序 builder.RegisterType<CalculaterInterceptor>(); // 注冊攔截器 builder.RegisterType<CalculaterInterceptor2>(); // 注冊攔截器2 var ioc = builder.Build(); var calculater = ioc.Resolve<ICalculater>(); var addResult = calculater.Add(2, 3); Console.WriteLine($"add result: {addResult}"); Console.WriteLine("-------------------"); Console.ReadLine(); }
我們看看輸出結果:
這里我們可以看出,執行順序為 CalculaterInterceptor --> CalculaterInterceptor2 --> Target Method --> CalculaterInterceptor2 --> CalculaterInterceptor 。攔截器中 invocation.Proceed() 方法用於調用下一個攔截器(若存在),直到最終的目標方法(Target Method)。不過 invocation.Proceed() 並不是一定要調用的,例如,對於有返回值的目標方法,我們在攔截器中設置 invocation.ReturnValue 值就可正確執行,這樣便不會執行目標方法。在有些場景中,如身份驗證、緩存讀取等還是特別有用的。
當然,在 Main() 方法中 Ioc 注冊 Caliculater 類型時我們注冊了兩個攔截器,".InterceptedBy(typeof(CalculaterInterceptor), typeof(CalculaterInterceptor2))"。我們也可以直接在 Calculater 類型 或 ICalculater 接口上以特性的形式注冊,如上面代碼中注釋掉的那部分。若是既有在類型上注冊,也有在 Autofac 的 Builder 中注冊,那么這個攔截器會重復執行。
基於類的攔截器:
我們定義兩個類 Flight 和其 子類 FlightOfSH:

public class Flight { public virtual void Fly(DateTime time) { Console.WriteLine($"Flight: {time}"); } } public class FlightOfSH : Flight { public override void Fly(DateTime time) { Console.WriteLine($"FlightOfSH: Fly={time}"); } public void Arrive(DateTime time) { Console.WriteLine($"FlightOfSH: Arrive={time}"); } }
這兩個類的攔截器:

internal class FlightInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { Console.WriteLine("Before Fly"); invocation.Proceed(); Console.WriteLine("After Fly"); } }

var builder = new ContainerBuilder(); builder.RegisterType<Flight>() .EnableClassInterceptors().InterceptedBy(typeof(FlightInterceptor)); builder.RegisterType<FlightOfSH>() .EnableClassInterceptors().InterceptedBy(typeof(FlightInterceptor)); builder.RegisterType<FlightInterceptor>(); var ioc = builder.Build(); var flight = ioc.Resolve<Flight>(); flight.Fly(DateTime.Now); var flightOfSH = ioc.Resolve<FlightOfSH>(); flightOfSH.Fly(DateTime.Now); flightOfSH.Arrive(DateTime.Now);