使用泛型类型的继承使用非预期的方法

时间:2017-12-27 04:50:57

标签: c# generics inheritance

我在标题上做得最好。我想要实现的是分层模块化和依赖注入。这种设计模式是否良好是another forum的问题。

因为我使用依赖注入,所以我有接口/实现对。这是顶级联系:

public interface IConfiguration<T> where T : ConfigData
{
    T GetConfig();
}

其中ConfigData是一个公开get / set属性的简单类,如LogLevelEnvironment

接口有一个基本实现:

public abstract class ConfigurationBase<T> : IConfiguration
{
    protected ConfigData Config { get; set; }

    public T GetConfig()
    {
        return Config as T;
    }
}

现在为依赖注入部分!我有几个接口/实现对,分层次地相互继承。此外,它们的protected Config属性还在每个后续子类中公开了更多属性。这是我的界面/实现签名:

public interface IGeneralConfiguration : IConfiguration<GeneralConfigData>
public class GeneralConfiguration : ConfigurationBase<GeneralConfigData>, IGeneralConfiguration

public interface ILoginConfiguration : IConfiguration<LoginConfigData>, IGeneralConfiguration
public class LoginConfiguration : ConfigurationBase<LoginConfigData>, ILoginConfiguration

public interface IAppConfiguration : IConfiguration<AppConfigData>, ILoginConfiguration
public class AppConfiguration : ConfigurationBase<AppConfigData>, IAppConfiguration

请注意,配置数据元素的继承方案是ConfigDataGeneralConfigDataLoginConfigDataAppConfigData。配置数据元素只公开每个子节点中特定于登录/应用程序等的更多属性(如UsernameStartUri)。

现在,我可以在所有模块中使用此配置概念。就依赖注入而言,解析IGeneralConfigurationILoginConfigurationIAppConfigurationyield the exact same instance。但是,现在一般模块只需要解析IGeneralConfiguration,特定于登录的模块只需要解析ILoginConfiguration,特定于应用程序的模块可以解析IAppConfiugration,以便他们可以访问部件他们的配置数据特定于他们正在尝试处理的问题。这种模块化允许我创建较小的副应用程序,可以重用主应用程序中的模块,而无需进行大量自定义编码(例如,我可以重用登录模块而无需引用特定于应用程序的模块),只要我略微改变我的依赖注册。

如果到目前为止你仍然和我在一起,那么这个模型的唯一问题就是在我的所有子类(继承自ConfigurationBase<T>)中,它们都需要ConfigData()的实现。他们上面的界面。这意味着class LoginConfiguration需要public GeneralConfigData GetConfig()的方法定义,而class AppConfiguration需要public GeneralConfigData GetConfig()以及LoginConfigData GetConfig()的方法定义。

太好了。我这样做。现在,在我的特定于应用程序的模块中,我收到编译器错误。在我的班级字段定义中,我有private IAppConfiguration _appConfiguration;。稍后在一个方法中,我引用它:

var element = _appConfiguration.GetConfig().AppSpecificConfigElement;

编译器很困惑,说

  

以下或属性'IConfiguration.GetConfig()'和'IConfiguration.GetConfig()'

之间的调用不明确

为什么编译器不会看到类型为IAppConfiguration并且定义GetConfig()AppConfiguration GetConfig()的调用T定义为AppConfigData)?

是否有一种明显的方法可以使用我的方案消除对GetConfig()的调用的歧义?

1 个答案:

答案 0 :(得分:1)

如果我理解正确那么你刚刚做的是你有两个具有相同签名的方法,除了无法自动解决的返回值。编译器没有(也不能)遍历从ConfigData派生的所有子类,以确定AppSpecificConfigElement属于AppConfiguration并根据它选择重载 - 即使它确实有多个具有AppSpecificConfigElement属性的类,因此它不会更加明智。您需要帮助编译器了解您的需要,方法是先键入_appConfiguration到正确的类型,或者先在语句中使用ConfigData的类型后代而不是var,然后获取属性。

在这两种情况下,我认为你认真过度设计,我建议退一步重新考虑你的方法。正如@zaitsman所说,这些对象应该是POCOs并且具有不同的加载器(DB,文件系统,...),实现简单的Load / Save接口,然后可以根据上下文传递给DI