c#, Unity IoC:注册和解析泛型接口,良好的实践

本文关键字:泛型接口 和解 IoC Unity 注册 | 更新日期: 2023-09-27 17:50:43

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

现在,当我查看我的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
}

其中ICountryConfig, ILanguageConfig,…是描述数据库实体的接口。然后提供商会小心地为依赖的组件提供正确的实体,这样对存储的访问就保持在自己的位置。

当我做了很少的重构时,问题出现了。我无意中使用了父接口而不是继承接口。当使用错误的接口类型时,它也可能非常脆弱。

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

// 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, ...)
{
    // ...
}

我现在需要的是一个好的建议。也许我在这里滥用国际奥委会太多了。中型项目的最佳方法是什么?


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

c#, Unity IoC:注册和解析泛型接口,良好的实践

如果每个提供程序都是不同的具体类型,那么这种方法是有效的,尽管使用空接口是冗长的。另一个不那么冗长的解决方案是泛化配置访问,这样你就有一个单一的配置"服务"来返回许多特定的配置blob中的任何一个。

Eg configProvider.GetConfig<IWhateverConfig>();

这样,你就不会充斥着大量的提供者的容器,本质上只是检索某种类型的属性包,充满了配置。您将注册单个配置提供程序,并在幕后将配置类型映射到配置部分。如果你公开了这个映射功能,那么配置blob可以在应用程序启动的任何时候以更模块化的方式注册。