C#中能否为父类注册装饰器使子类自动生效无需创建对应子类装饰器
泛型仓储装饰器批量注册问题
现有代码结构
基础仓储(父类)定义:
public interface IBaseRepository<TEntity, TId> where TEntity : class, IEntity<TId> public class BaseRepository<TEntity, TId> : IRepository<TEntity, TId>
特定业务仓储(子类)定义:
public interface IUserRepository : IRepository<User,Guid> public class UserRepository<User,Guid> : BaseRepository<User,Guid>, IUserRepository
通用装饰器定义:
public class BaseRepositoryDecorator<TEntity, TId> : IRepository<TEntity, TId>
问题描述
目前的验证结果:如果手动创建UserRepositoryDecorator并继承自BaseRepositoryDecorator,通过SimpleInjector或Scrutor注册后可以正常触发装饰逻辑。
想确认是否可以跳过为每个子类仓储单独创建[子类名]RepositoryDecorator(例如上述的UserRepositoryDecorator)的步骤,直接通过父类开放泛型装饰器实现全局装饰,让子类实例调用时也能触发装饰逻辑。
解答
完全可以实现,不需要为每个子类单独定义对应装饰器。
之前需要单独定义子类装饰器才能运行,本质是注册时没有正确配置开放泛型的匹配规则,两个常用DI扩展库都原生支持开放泛型装饰器的全局自动装饰:
Simple Injector 配置
Simple Injector原生对开放泛型装饰器有完善支持,直接注册开放泛型装饰器即可,框架会自动为所有IRepository<TEntity,TId>的实现(包括继承该接口的子接口如IUserRepository对应的实例)套上装饰层:
// 注册仓储实现,可批量扫描注册也可单独注册 container.Register(typeof(IRepository<,>), typeof(BaseRepository<,>).Assembly); container.Register<IUserRepository, UserRepository>(); // 注册开放泛型装饰器,自动匹配所有符合泛型约束的IRepository<,>实例 container.RegisterDecorator( serviceType: typeof(IRepository<,>), decoratorType: typeof(BaseRepositoryDecorator<,>));
Scrutor 配置
Scrutor作为微软原生DI的扩展库,同样支持开放泛型装饰器全局注册:
// 批量扫描注册仓储 services.Scan(scan => scan .FromAssemblyOf<BaseRepository<,>>() .AddClasses(classes => classes.AssignableTo(typeof(IRepository<,>))) .AsImplementedInterfaces() .WithScopedLifetime()); // 全局注册开放泛型装饰器 services.Decorate(typeof(IRepository<,>), typeof(BaseRepositoryDecorator<,>));
注意事项
- 通用装饰器
BaseRepositoryDecorator<,>的构造函数必须注入一个IRepository<TEntity,TId>类型的参数,用来持有被装饰的原始仓储实例,这是装饰器模式的基本要求。 - 如果有个别仓储不需要被装饰,直接在注册装饰器时添加过滤规则即可,不需要单独定义子类装饰器。
- 只要子接口(比如
IUserRepository)继承自IRepository<,>对应闭合泛型版本,通过子接口解析实例时装饰逻辑会正常生效,不需要对子接口做额外适配。
内容的提问来源于stack exchange,提问作者Diego-gs
相关产品推荐
相关产品推荐

