如何在C#派生类中永久向下转换泛型设置类?
问题:派生服务类无法直接访问设置类的专属属性,需避免强制转换
我拥有多个具备相似行为的服务,这些服务均包含共享设置,同时每个服务还有自身的扩展专属设置,但在派生服务类中无法直接访问这些扩展设置,只能通过强制转换获取。以下是实现示例及问题:
public abstract class BaseSettings<T> where T : ISettings { public string BaseSetting { get; } = "Hello from BaseSettings"; // other settings, etc. public BaseSettings<T>() {} } public abstract class BaseService<T> where T : ISettings { public BaseSettings<T> Settings { get; } public BaseService(BaseSettings<T> settings) { Settings = settings; Console.WriteLine(Settings.BaseSetting); } } public class ServiceASettings : BaseSettings<ServiceASettings>, ISettings { public string SettingA { get; } = "Hello from SettingsA"; public ServiceASettings() {} } public class ServiceA : BaseService<ServiceASettings>, IService { public ServiceA(ServiceASettings settings) : base(settings) { Console.WriteLine(Settings.SettingA); // 无法访问该属性 Console.WriteLine((Settings as ServiceASettings).SettingA); // 强制转换后可正常输出 } } // ServiceB, ServiceBSettings; ServiceC, ServiceCSettings; etc... public class Program { public static void Main(string[] args) { ServiceASettings settings = new ServiceASettings(); ServiceA service = new ServiceA(settings); // 编译失败,提示ServiceA中没有Settings.SettingA的定义 } }
我希望能永久将Settings指定为对应的派生类类型,避免每次都进行强制转换,请问该如何实现?
解决方案
修改后的可运行代码如下:
public abstract class BaseSettings { public string BaseSetting { get; } = "Hello from BaseSettings"; // other settings, etc. public BaseSettings() {} } public abstract class BaseService<T> where T : ISettings { public T Settings { get; } public BaseService(T settings) { Settings = settings; Console.WriteLine(Settings.BaseSetting); } } public class ServiceASettings : BaseSettings, ISettings { public string SettingA { get; } = "Hello from SettingsA"; public ServiceASettings() {} } public class ServiceA : BaseService<ServiceASettings>, IService { public ServiceA(ServiceASettings settings) : base(settings) { Console.WriteLine(Settings.SettingA); // 现在可直接访问专属属性 } } public class Program { public static void Main(string[] args) { ServiceASettings settings = new ServiceASettings(); ServiceA service = new ServiceA(settings); } }
修改说明
- 移除
BaseSettings的泛型定义,将其改为普通抽象类,作为所有设置类的基类,保留共享设置属性 - 将
BaseService<T>中的Settings属性类型从BaseSettings<T>改为泛型参数T,同时构造函数参数也改为T - 派生设置类直接继承
BaseSettings并实现ISettings接口
这样修改后,派生服务类中的Settings属性会直接对应到具体的派生设置类类型,无需强制转换即可访问专属属性。
内容的提问来源于stack exchange,提问作者Zerosum
相关产品推荐
相关产品推荐

