正如其他人指出的那样,PostSharp 之类的工具允许您在编译期间(实际上是之后)编织横切逻辑。
另一种方法是在运行时进行。一些 IoC 工具允许您定义拦截器,然后将这些拦截器添加到您的实现的代理类中。这听起来比实际复杂得多,所以我将展示一个基于 Castle DynamicProxy 的示例。
首先,您定义需要包装的类。
[Interceptor(typeof(SecurityInterceptor))]
public class OrderManagementService : IOrderManagementService
{
[RequiredPermission(Permissions.CanCreateOrder)]
public virtual Guid CreateOrder(string orderCode)
{
Order order = new Order(orderCode);
order.Save(order); // ActiveRecord-like implementation
return order.Id;
}
}
RequiredPermission
在这里充当装饰者。类本身装饰有Interceptor
指定接口方法调用的处理程序的属性。这也可以放入配置中,因此对类隐藏。
拦截器实现包含装饰器逻辑
class SecurityInterceptor : IMethodInterceptor
{
public object Intercept(IMethodInvocation invocation, params object[] args)
{
MethodInfo method = invocation.Method;
if (method.IsDefined(typeof(RequiredPermission), true) // method has RequiredPermission attribute
&& GetRequiredPermission(method) != Context.Caller.Permission) {
throw new SecurityException("No permission!");
}
return invocation.Proceed(args);
}
private Permission GetRequiredPermission(MethodInfo method)
{
RequiredPermission attribute = (RequiredPermission)method.GetCustomAttributes(typeof(RequiredPermission), false)[0];
return attribute.Permission;
}
}
但是也有一些缺点:
- 使用 DynamicProxy 你只能包装接口和虚拟方法。
- 您需要通过 IoC 容器而不是直接实例化对象(如果您已经使用 IoC 容器,这不是问题)