Java 有 AOP 和 aspectJ 和编织(LTW 加载时间和代理,编译时间 CTW) C#(城堡)有拦截器,也使用(动态)代理。您可以将其视为 LTW 变体。
我在 c# 中使用了这个设置。这不是什么大魔法,而且代码也很有限。
Autofac 5.1.0
Autofac.Extras.DynamicProxy 5.0.0
Castle.Core 4.4.0
诀窍是
- 定义一些属性,用作拦截器属性
- 定义一个拦截器,检查被调用方法的属性
- 使用方法和接口方法上的属性定义接口
- 定义接口的实现类
- 使用 autofac 注册整个设置
- 测试/运行/开始
1)定义一些属性
using System;
[AttributeUsage(
AttributeTargets.Method,
AllowMultiple = true)]
public class SomeAttribute : Attribute
{
public long Id { get; set; }
}
2)定义一个城堡动态拦截器(又名代理)
using Castle.DynamicProxy;
using System;
public class SomeInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
if (Attribute.IsDefined(invocation.Method, typeof(SomeAttribute)))
{
Console.Write("Method called: " + invocation.Method.Name);
}
invocation.Proceed();
}
}
现在,创建一个带有接口的对象(不要忘记,将属性放在接口上,而不是在 impl 上!)
3) 定义接口
public interface AOPTest
{
[Some(Id = 10)]
void DoSomething();
}
4)定义实现:
public class AOPTestImpl : AOPTest
{
public void DoSomething()
{
}
}
5) 使用 autofac 注册整个设置
builder.RegisterType<AOPTestImpl>()
.As<AOPTest>()
.EnableInterfaceInterceptors()
.InterceptedBy(typeof(SomeInterceptor));
builder.RegisterType<SomeInterceptor>().AsSelf();
6) test/run/go :运行整个设置:
using Autofac;
using Autofac.Extras.DynamicProxy;
using (var scope = bootstrap.BootStrap.Container.BeginLifetimeScope())
{
var aOPTest = scope.Resolve<AOPTest>();
aOPTest.DoSomething();
}
我不知道它是如何工作的,但想法是:
接口 -> 代理 -> 实现 因此,如果您通过接口调用实现,则代理/拦截器介于两者之间。
注意:如果你在 doSomething() 方法中调用其他代码也需要拦截,你可能需要一个 autofac 类拦截器 EnableClassInterceptors
注意:这不是世界上最快的解决方案。可能一些过滤拦截器更快,像 Fody 或 PostSharp 这样的编译时间编织可能更快。但这会做很多次。
注意:如果您需要在方法开始之前完成某些操作,请在调用之前对其进行编码。Proceed(); 如果您需要在最后完成某些事情,请在调用 @After invocation.Proceed() 时对其进行编码:
@前
做一点事(){...}
@后