C#、Unity IoC:注册和解析通用接口,良好实践

C#, Unity IoC: Registering and resolving generic interfaces, good practices

我编写了通用接口,随着时间的推移,我开始经常使用它。我还想提供另一个通用接口,扩展现有接口。

现在,当我查看我的 Unity 配置(此处与 IoC 框架无关)时,它看起来像这样:

container.RegisterType<IConfigProvider<ICountryConfig>, CountryConfigProvider>();
container.RegisterType<IConfigProvider<ILanguageConfig>, LanguageConfigProvider>();

// IEnumerableConfigProvider<T> : IConfigProvider<IEnumerable<T>>
container.RegisterType<IEnumerableConfigProvider<ILocaleConfig>, LocaleConfigProvider>();

// ... repeat gazillion of times...

作为依赖使用:

public LocaleResolver(IConfigProvider<ICountryConfig> countryConfigProvider, ...)
{
    // similar construct all over the place
}

其中 ICountryConfigILanguageConfig、... 是描述数据库实体的接口。提供程序然后注意向依赖组件提供正确的实体,以便对存储的访问保留在自己的位置。

当我几乎没有重构时出现了问题。我不小心使用了父接口而不是继承的接口。当使用错误的接口类型时,它也可能非常脆弱。

这让我产生了(显而易见的)想法,即创建另一层接口来封装具体用法。这将解决上述问题,另一方面,我最终会为每个可能的实现提供万亿个空接口。

// ICountryConfigProvider : IConfigProvider<ICountryConfig>
container.RegisterType<ICountryConfigProvider, CountryConfigProvider>();

// ILanguageConfigProvider : IConfigProvider<ILanguageConfig>
container.RegisterType<ILanguageConfigProvider, LanguageConfigProvider>();

// ILocaleConfigProvider : IEnumerableConfigProvider<ILocaleConfig>
container.RegisterType<ILocaleConfigProvider, LocaleConfigProvider>();

它的用法更简洁:

public LocaleResolver(ICountryConfigProvider countryConfigProvider, ...)
{
    // ...
}

而我现在正在寻找的是一个很好的建议。也许我在这里过度滥用 IoC。中型项目的最佳方法是什么?


我知道这个话题可能会以讨论结束,而不是具体的答案,我为亲爱的 Whosebug 道歉。

如果每个提供者都是不同的具体类型,那么这种方法虽然带有空接口,但很冗长,但也是有效的。另一个不那么冗长的解决方案是概括配置访问,因此您只有一个配置 'service' returns 许多特定配置 blob 中的任何一个。

Eg configProvider.GetConfig<IWhateverConfig>();

这样一来,您就不会在容器中塞满大量提供程序,本质上只是检索某种类型的 属性 装满配置的包。您将注册一个配置提供程序,并在幕后将配置类型映射到配置部分。如果您公开此映射功能,则可以在应用程序启动期间的任何时候以更模块化的方式注册配置 blob。