C#带保护方法的类继承设计与运行时基类处理器问题
问题分析
你的核心矛盾在于:
- 原有
SecretConfigurations同时用继承(继承BaseConfigurations)和依赖注入(注入ICRUDHandler),但注入的实例是独立对象,无法触发SecretConfigurations重写的ProtectedMethod——因为实例方法属于当前对象,注入的BaseConfigurations/V2和SecretConfigurations是两个完全独立的实例。 - 为
BaseConfigurationsV2单独写SecretConfigurationsV2会重复所有Secret相关逻辑,违反DRY原则。
下面是两种无代码重复的解决方案:
方案1:装饰器模式(推荐)
把Secret相关逻辑抽成装饰器类,实现ICRUDHandler接口,内部持有任意ICRUDHandler实例(BaseConfigurations或V2),通过组合而非继承来复用Secret逻辑,适配所有CRUD实现版本。
代码实现
// 定义Secret装饰器,实现ICRUDHandler public class SecretCRUDHandlerDecorator : ICRUDHandler { private readonly ICRUDHandler _innerHandler; // 构造函数注入任意ICRUDHandler实例 public SecretCRUDHandlerDecorator(ICRUDHandler innerHandler) { _innerHandler = innerHandler; } // 实现CreateSetting,添加Secret专属逻辑 public void CreateSetting(Setting setting) { // 原ProtectedMethod中的Secret前置逻辑 ApplySecretPreProcessing(setting); // 调用内部handler的原生Create逻辑 _innerHandler.CreateSetting(setting); // 可选:Secret后置逻辑 ApplySecretPostProcessing(setting); } // 实现GetSetting,添加解密逻辑 public Setting GetSetting(string key) { var setting = _innerHandler.GetSetting(key); // Secret专属解密逻辑 DecryptSetting(setting); return setting; } // 其他CRUD方法(Update/Delete)同理,按需添加Secret逻辑后调用_innerHandler对应方法 public void UpdateSetting(Setting setting) { ApplySecretPreProcessing(setting); _innerHandler.UpdateSetting(setting); } // Secret专属逻辑封装为私有方法,只写一次 private void ApplySecretPreProcessing(Setting setting) { // 原SecretConfigurations中ProtectedMethod的逻辑 // 例如:加密敏感字段、校验权限等 } private void ApplySecretPostProcessing(Setting setting) { // 例如:记录审计日志、清理临时数据等 } private void DecryptSetting(Setting setting) { // 解密敏感字段逻辑 } }
使用方式
运行时选择基础CRUD实例,再用装饰器包装成Secret版本:
// 运行时切换Base或V2实例 ICRUDHandler baseHandler = someCondition ? new BaseConfigurations() : new BaseConfigurationsV2(); // 包装为Secret版本,无需新增子类 ICRUDHandler secretHandler = new SecretCRUDHandlerDecorator(baseHandler);
优势
- Secret逻辑只写一次,适配所有
ICRUDHandler实现,新增CRUD版本时无需修改Secret代码 - 完全解耦Secret逻辑与基础CRUD逻辑,符合单一职责原则
- 避免继承带来的耦合,用组合实现灵活扩展
方案2:提取Secret逻辑为独立服务
把Secret逻辑抽成独立服务,让BaseConfigurations和V2通过依赖注入复用该服务,无需额外子类。
代码实现
- 定义Secret处理器接口与实现:
public interface ISecretProcessor { void PreProcessSetting(Setting setting); void PostProcessSetting(Setting setting); void DecryptSetting(Setting setting); } public class SecretProcessor : ISecretProcessor { public void PreProcessSetting(Setting setting) { // 原ProtectedMethod中的Secret前置逻辑 } public void PostProcessSetting(Setting setting) { // Secret后置逻辑 } public void DecryptSetting(Setting setting) { // 解密逻辑 } }
- 修改基础CRUD类,注入
ISecretProcessor:
public class BaseConfigurations : ICRUDHandler { protected readonly ISecretProcessor _secretProcessor; // 可选注入,兼容普通场景和Secret场景 public BaseConfigurations(ISecretProcessor secretProcessor = null) { _secretProcessor = secretProcessor; } public virtual void CreateSetting(Setting setting) { // 存在Secret处理器时执行前置逻辑 _secretProcessor?.PreProcessSetting(setting); // 原生Create逻辑 // ... _secretProcessor?.PostProcessSetting(setting); } public virtual Setting GetSetting(string key) { var setting = // 原生读取逻辑; _secretProcessor?.DecryptSetting(setting); return setting; } } // BaseConfigurationsV2自动继承对ISecretProcessor的依赖 public class BaseConfigurationsV2 : BaseConfigurations { public BaseConfigurationsV2(ISecretProcessor secretProcessor = null) : base(secretProcessor) { } // 仅重写V2专属的CRUD逻辑,无需重复Secret代码 public override void CreateSetting(Setting setting) { _secretProcessor?.PreProcessSetting(setting); // V2专属Create逻辑 // ... _secretProcessor?.PostProcessSetting(setting); } }
使用方式
根据场景选择是否注入SecretProcessor:
// 普通场景 ICRUDHandler normalHandler = someCondition ? new BaseConfigurations() : new BaseConfigurationsV2(); // Secret场景 var secretProcessor = new SecretProcessor(); ICRUDHandler secretHandler = someCondition ? new BaseConfigurations(secretProcessor) : new BaseConfigurationsV2(secretProcessor);
优势
- Secret逻辑集中管理,无重复代码
- 保留基础CRUD类的继承关系,同时通过依赖注入解耦Secret逻辑
- 兼容普通和Secret两种场景
内容的提问来源于stack exchange,提问作者CodeMonkey
相关产品推荐
相关产品推荐

