? ? ? ? AOP(面向切片編程的概念我這里就不介紹了,這里先介紹一下C#中的AOP編程框架。
1.AOP的分類
? ? ? ? .net下支持AOP的框架很多,搜了一下有:PostSharp、AspectInjector、Fody 、Castle Windsor、Spring.NET、Ninject、Unity等,實現的方式主要氛圍兩大類:
- 編譯時織入:通常在運行時性能較好,但編譯時間可能增加。上面的紅色框架
- 動態代理:通常在高頻調用時會有額外的性能開銷。上面的藍色框架。
1.編譯時織入舉例
? ? ? ? PostSharp是非開源的,這里以AspectInjector為例:
using AspectInjector.Broker;Console.WriteLine("Hello, World!");
MyClass myClass = new MyClass();
myClass.MyMethod();[Aspect(Scope.Global)]
[Injection(typeof(LogAttribute))]
public class LogAttribute : Attribute
{[Advice(Kind.Before)]public void Before([Argument(Source.Name)]string name){Console.WriteLine($"Entering method: {name}");}[Advice(Kind.After)]public void After([Argument(Source.Name)] string name){Console.WriteLine($"Exiting method: {name}");}
}public class MyClass
{[Log]public void MyMethod(){Console.WriteLine("Executing MyMethod");}
}
運行結果如下:
Hello, World!
Entering method: MyMethod
Executing MyMethod
Exiting method: MyMethod
想了解更多可以參考AspectInjector的官方文檔
2.動態代理舉例
? ? ? ? 單純的動態代理其實需要手動編寫的代碼較多,一般是結合依賴注入容器來使用。這個以比較常用的Autofac 依賴注入容器為例:
- 首先,通過 NuGet 安裝 Autofac 和動態代理支持:
Install-Package Autofac
Install-Package Autofac.Extras.DynamicProxy
- ?創建接口和實現類
定義一個接口和它的實現類:
public interface IMessageService
{void SendMessage(string message);
}public class EmailService : IMessageService
{public void SendMessage(string message){Console.WriteLine($"Email sent: {message}");}
}
- 3. 創建攔截器
定義一個攔截器類,用于實現 AOP 功能:
using Castle.DynamicProxy;
using System;public class LoggingInterceptor : IInterceptor
{public void Intercept(IInvocation invocation){Console.WriteLine($"Entering method: {invocation.Method.Name}");invocation.Proceed(); // 調用原方法Console.WriteLine($"Exiting method: {invocation.Method.Name}");}
}
-
設置 Autofac 容器
在 Autofac 容器中注冊服務和攔截器:
using Autofac;public class Program
{static void Main(string[] args){var builder = new ContainerBuilder();builder.RegisterType<EmailService>().As<IMessageService>().EnableInterfaceInterceptors().InterceptedBy(typeof(LoggingInterceptor));builder.RegisterType<LoggingInterceptor>();var container = builder.Build();var messageService = container.Resolve<IMessageService>();messageService.SendMessage("Hello, Autofac with AOP!");}
}
運行結果:
Entering method: SendMessage
Email sent: Hello, Autofac with AOP!
Exiting method: SendMessage
可以看到我們成功的實現了在原函數前后插入執行代碼。動態代理在web服務使用較多。