如何避免新增服务类时修改C#派生类的构造函数?
解决派生类随基类新增服务而修改构造函数的问题
首先,我们可以通过抽象服务共性+依赖注入集合的方式来解决这个问题,核心思路是避免基类依赖具体的服务类,转而依赖服务的抽象接口,同时让基类接收服务集合而非单个服务参数,这样新增服务时派生类完全不需要修改。
步骤1:定义服务抽象接口
先给所有需要设置UserEmail的服务类定义一个统一接口,提取共同的UserEmail属性:
public interface IUserEmailService { string UserEmail { get; set; } }
然后让所有服务类实现这个接口:
public class ServiceClass1 : IUserEmailService { public string UserEmail { get; set; } // 其他原有业务代码 } public class ServiceClass2 : IUserEmailService { public string UserEmail { get; set; } // 其他原有业务代码 } public class ServiceClass3 : IUserEmailService { public string UserEmail { get; set; } // 其他原有业务代码 }
步骤2:重构基类构造函数
修改基类,让它接收IEnumerable<IUserEmailService>类型的参数,这样不管新增多少服务,基类只需要遍历集合设置UserEmail即可,无需修改构造函数参数。如果需要单独访问某个服务,可以保留对应属性,新增服务时仅需添加属性,不用改构造函数:
public class BaseClass { // 保留单独访问服务的属性(按需选择) public ServiceClass1 Sc1 { get; } public ServiceClass2 Sc2 { get; } public ServiceClass3 Sc3 { get; } // 接收所有实现IUserEmailService的服务集合 public BaseClass(IEnumerable<IUserEmailService> userEmailServices, ServiceClass1 sc1, ServiceClass2 sc2, ServiceClass3 sc3) { Sc1 = sc1; Sc2 = sc2; Sc3 = sc3; // 统一遍历设置UserEmail,新增服务无需修改此处 var userEmail = (string)Session["UserEmail"]; foreach (var service in userEmailServices) { service.UserEmail = userEmail; } } }
步骤3:重构派生类构造函数
现在派生类的构造函数只需要传递集合和必要的单个服务给基类,后续新增服务时,派生类完全不需要修改构造函数:
public class DerivedClass1 : BaseClass { public DerivedClass1(IEnumerable<IUserEmailService> userEmailServices, ServiceClass1 sc1, ServiceClass2 sc2, ServiceClass3 sc3) : base(userEmailServices, sc1, sc2, sc3) { } } public class DerivedClass2 : BaseClass { public DerivedClass2(IEnumerable<IUserEmailService> userEmailServices, ServiceClass1 sc1, ServiceClass2 sc2, ServiceClass3 sc3) : base(userEmailServices, sc1, sc2, sc3) { } }
步骤4:Unity DI配置
在Unity容器中注册所有IUserEmailService的实现,Unity会自动将所有匹配的实例注入到IEnumerable<IUserEmailService>参数中:
var container = new UnityContainer(); // 注册所有实现IUserEmailService的服务 container.RegisterType<IUserEmailService, ServiceClass1>(); container.RegisterType<IUserEmailService, ServiceClass2>(); container.RegisterType<IUserEmailService, ServiceClass3>(); // 后续新增ServiceClass4时,仅需添加这一行: // container.RegisterType<IUserEmailService, ServiceClass4>(); // 注册基类和派生类 container.RegisterType<BaseClass>(); container.RegisterType<DerivedClass1>(); container.RegisterType<DerivedClass2>();
更精简的方案(无需单独访问服务时)
如果你的基类和派生类不需要单独调用某个服务的方法,只是需要设置UserEmail,可以进一步简化:基类完全不需要单个服务属性,只依赖集合。这种情况下,新增服务时连基类都不需要修改:
public class BaseClass { public BaseClass(IEnumerable<IUserEmailService> userEmailServices) { var userEmail = (string)Session["UserEmail"]; foreach (var service in userEmailServices) { service.UserEmail = userEmail; } } } public class DerivedClass1 : BaseClass { public DerivedClass1(IEnumerable<IUserEmailService> userEmailServices) : base(userEmailServices) { } } public class DerivedClass2 : BaseClass { public DerivedClass2(IEnumerable<IUserEmailService> userEmailServices) : base(userEmailServices) { } }
此时新增服务仅需两步:让新服务实现IUserEmailService、在Unity中注册该服务,完全不需要改动基类和派生类的代码。
内容的提问来源于stack exchange,提问作者Thomas.Benz
相关产品推荐
相关产品推荐

