Castle Core With Autofac

在上一篇介紹 Castle Core 基礎的文章,中有介紹到 安裝 Castle Core 的主要目的就是為了它的 DynamicProxy 來實做 AOP 的功能。

但是這種手動建立 ProxyGenerator 與使用 CreateInterfaceProxyWithTarget 綁定介面的方式在實務上不用這麼麻煩, 通常會在額外搭配 IOC 容器以達到更流暢的使用體驗,例如 AspectCore 這套函式庫也有跟各個 IOC 容器進行整合,比較常用的有 AspectCore.Extensions.DependencyInjectionAspectCore.Extensions.Autofac

Castle Core 也有提供類似的整合函式庫,第一種就是直接使用 Castle 團隊開發的 IOC 容器叫做 Castle Windsor, 但它也是比較古老的專案,在微軟官方的 IOC 容器推出前就已經存在。

另一種就是使用 Autofac 這套 IOC 容器與 Autofac 官方提供的額外函式庫 Autofac.Extras.DynamicProxy,它內部就是使用了 Castle Core 專案來做到 DynamicProxy 的功能,在實務上建議是安裝 Autofac.Extensions.DependencyInjection 函式庫, 因為它是根據 Microsoft.Extensions.DependencyInjection 定義的抽象介面所建立出來的。

安裝函式庫與實做

所以接下來只要安裝這兩個函式庫即可整合 Autofac IOC 容器與 Castle Core 的 DynamicProxy 功能。

dotnet add package Autofac.Extensions.DependencyInjection
dotnet add package Autofac.Extras.DynamicProxy

呼叫的方式也很簡單,就是在註冊服務的時候記得呼叫 EnableInterfaceInterceptors 擴充方法,它背後會對這個介面進行標記,之後只需要 在實做類別使用 InterceptAttribute 說明要使用的攔截器即可。

另一種綁定方式就是透過 InterceptedBy 擴充方法直接與攔截器進行綁定就不用使用 InterceptAttribute 了。

void Main()
{
	var builder = new ContainerBuilder();
	
	builder.RegisterType<Hello>()
		.As<IHello>()
		//.InterceptedBy(typeof(TimingInterceptor))
		.EnableInterfaceInterceptors();
		
	builder.Register(c => new TimingInterceptor());
	var container = builder.Build();
	var service = container.Resolve<IHello>();
	service.SayHello();
}

public class TimingInterceptor : IInterceptor
{
	public void Intercept(IInvocation invocation)
	{
		var stopwatch = new Stopwatch();
		stopwatch.Start();
		invocation.Proceed();
		stopwatch.Stop();
		Console.WriteLine(stopwatch.Elapsed);
	}
}

[Intercept(typeof(TimingInterceptor))]
public class Hello : IHello
{
	public void SayHello()
	{
		Thread.Sleep(1000);
		Console.WriteLine("Hello");
	}
}

public interface IHello
{
	public void SayHello();
}

最後就可以使用 Resolve 方法從 IOC 容器中取得需要的服務,Autofac 背後就會自行處理 new ProxyGenerator()CreateInterfaceProxyWithTarget 這些邏輯了。

自行建立 ProxyGenerator 不建議每次都創建新的 ProxyGenerator,最好是將它定義成靜態的否則會消耗許多記憶體容量, 使用 Autofac.Extras.DynamicProxy 的另一個好處就是我們不需要關注這些小細節,只需要專心實做商業邏輯就好。