AOP(面向切片编程的概念我这里就不介绍了,这里先介绍一下C#中的AOP编程框架。
1.AOP的分类
.net下支持AOP的框架很多,搜了一下有:PostSharp、AspectInjector、Fody 、Castle Windsor、Spring.NET、Ninject、Unity等,实现的方式主要氛围两大类:
- 编译时织入:通常在运行时性能较好,但编译时间可能增加。上面的红色框架
- 动态代理:通常在高频调用时会有额外的性能开销。上面的蓝色框架。
1.编译时织入举例
PostSharp是非开源的,这里以AspectInjector为例:
cs
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");
}
}
运行结果如下:
cs
Hello, World!
Entering method: MyMethod
Executing MyMethod
Exiting method: MyMethod
想了解更多可以参考AspectInjector的官方文档
2.动态代理举例
单纯的动态代理其实需要手动编写的代码较多,一般是结合依赖注入容器来使用。这个以比较常用的Autofac 依赖注入容器为例:
- 首先,通过 NuGet 安装 Autofac 和动态代理支持:
cs
Install-Package Autofac
Install-Package Autofac.Extras.DynamicProxy
- 创建接口和实现类
定义一个接口和它的实现类:
cs
public interface IMessageService
{
void SendMessage(string message);
}
public class EmailService : IMessageService
{
public void SendMessage(string message)
{
Console.WriteLine($"Email sent: {message}");
}
}
-
- 创建拦截器
定义一个拦截器类,用于实现 AOP 功能:
cs
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 容器中注册服务和拦截器:
cs
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!");
}
}
运行结果:
cs
Entering method: SendMessage
Email sent: Hello, Autofac with AOP!
Exiting method: SendMessage
可以看到我们成功的实现了在原函数前后插入执行代码。动态代理在web服务使用较多。