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

时间:2015-05-24 10:00:45

标签: c# generics architecture unity-container

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

现在,当我查看我的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,...是描述数据库实体的接口。然后,Provider会小心地为依赖组件提供正确的实体,因此存储的访问权限保留在自己的位置。

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

这促使我(明显)想到创建另一层接口来封装具体用法。这将解决上述问题,另一方面,我将为每个可能的实现提供万亿个空接口。

// 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太多了。中型项目的最佳方法是什么?

我知道这个主题最终可能会讨论而不是具体的答案,我为亲爱的StackOverflow道歉。

1 个答案:

答案 0 :(得分:0)

如果每个提供者都是不同的具体类型,那么这种方法虽然对空接口很冗长,但是有效。另一个不那么冗长的解决方案是概括配置访问,因此您只需要一个配置“服务”即可返回许多特定配置blob中的任何一个。

Eg configProvider.GetConfig<IWhateverConfig>();

通过这种方式,您不会充斥大量提供程序的容器,因为它本质上只是检索特定类型的属性包充满了配置。您将注册一个配置提供程序,并在封面下将配置类型映射到配置部分。如果您公开了这种映射功能,那么在应用程序启动期间的任何时候都可以以更模块化的方式注册配置blob。