自动实现装饰器方法:数据访问类授权装饰模式的自动化实现问询
自动实现装饰器中的授权逻辑
你用装饰器模式给数据访问类加授权校验的思路没问题,但手动给每个接口方法重复写AuthorizationHelper.Instance.Authorize()确实太繁琐了。下面几个方案能帮你自动完成这个重复工作,不用再挨个方法编写授权逻辑:
1. 使用动态代理库(比如Castle DynamicProxy)
动态代理可以在运行时自动生成实现接口的代理类,给所有方法统一注入前置的授权逻辑。
实现步骤:
- 先安装Castle.Core NuGet包:
Install-Package Castle.Core
- 创建一个拦截器类,实现
IInterceptor接口来封装授权逻辑:
public class AuthorizationInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { // 先执行授权校验 AuthorizationHelper.Instance.Authorize(); // 再调用原接口方法 invocation.Proceed(); } }
- 用代理生成器创建带授权逻辑的实例:
var proxyGenerator = new ProxyGenerator(); var authInterceptor = new AuthorizationInterceptor(); IUserData authorizedUserData = proxyGenerator.CreateInterfaceProxyWithTarget( new UserData(), authInterceptor);
这样调用authorizedUserData的任何方法时,都会自动先执行授权校验,完全不用手动写每个方法的装饰代码。
2. 利用.NET AOP框架(比如AspectCore)
如果你的项目是.NET Core/.NET 5+,AspectCore这类轻量级AOP框架能更优雅地实现需求。
实现步骤:
- 安装AspectCore.Core NuGet包:
Install-Package AspectCore.Core
- 定义一个授权切面特性:
public class AuthorizationAttribute : AbstractInterceptorAttribute { public override async Task Invoke(AspectContext context, AspectDelegate next) { AuthorizationHelper.Instance.Authorize(); await next(context); } }
- 给目标接口或方法标记这个特性:
[Authorization] interface IUserData { User GetUser(uint id); User ByName(string username); }
- 通过代理生成器获取带授权的实例:
var proxyGenerator = new ProxyGenerator(); IUserData authorizedUserData = proxyGenerator.CreateProxy<IUserData>(new UserData());
所有标记了[Authorization]的方法都会自动触发授权逻辑。
3. 手写通用装饰器(无第三方依赖)
如果不想引入外部库,也可以用.NET自带的DispatchProxy实现一个通用装饰器:
实现代码:
public class GenericAuthorizedDecorator<T> : DispatchProxy { private T _targetInstance; protected override object Invoke(MethodInfo targetMethod, object[] args) { // 执行授权校验 AuthorizationHelper.Instance.Authorize(); // 调用目标对象的原方法 return targetMethod.Invoke(_targetInstance, args); } public static T Create(T target) { object proxy = Create<T, GenericAuthorizedDecorator<T>>(); ((GenericAuthorizedDecorator<T>)proxy)._targetInstance = target; return (T)proxy; } }
使用方式:
IUserData authorizedUserData = GenericAuthorizedDecorator<IUserData>.Create(new UserData());
这个方案完全依赖.NET原生API,不需要额外安装包,适合轻量场景。
你可以根据自己的项目环境和复杂度,选一个最合适的方案就行。
内容的提问来源于stack exchange,提问作者Mike Cluck
相关产品推荐
相关产品推荐

