当需要不同的参数时,如何注入依赖项?

时间:2011-11-09 09:17:19

标签: dependency-injection inversion-of-control

例如我有这段代码

public class ProductService{
private IProductDataSource _dataSource = DependencyManager.Get<IProductDataSource>();
public Product Get(int id){
return _dataSource.Select(id);
}
}

我有2个不同的数据源:

  • 仅包含1种语言的信息的XML文件
  • 包含多种语言信息的SQL数据库。

所以我为IProductDataSource创建了2个实现,用于各种数据源。 但是如何将所需语言发送到SQL数据源?

  • 我将参数“language”添加到方法“IProductDataSource.Select”中,即使我不会在XML实现的情况下使用它。
  • 在SQL实现中,我从全局状态获取语言?
  • 我将语言添加到我的SQL实现的构造函数中,但后来我不会使用我的DependencyManager并处理我自己的依赖注入。

也许我的第一个解决方案并不好。

3 个答案:

答案 0 :(得分:5)

第三种选择是要走的路。将语言配置注入SQL实现。还要删除你的DependencyManager ServiceLocator并使用构造函数注入。

答案 1 :(得分:1)

如果您的应用程序需要在单个实例中使用多种语言,我认为第一点是一种明智的方法。如果基础数据不提供请求语言的翻译,则返回null。在这种情况下还有另一种解决方案。我假设您拥有的是每种产品的产品和语言翻译列表。您是否可以重构模型,以便在引用特定于语言的文本之前不需要指定或确定语言?无论您选择何种语言来描述产品,产品都是一种产品。即每个产品一个产品实例,只有Datasource.Select(..)方法上的产品ID和一些其他抽象机制来处理访问正确的文本翻译。

但是,如果您的申请的每个实例仅涉及一种语言集,那么第二位Gloor先生。

答案 2 :(得分:0)

首先,我需要指出的是,您并没有在示例中注入任何依赖项 - 您依赖于服务定位器(DependencyManager)来为您获取它们。简单地说,依赖注入就是当你的类不知道谁提供依赖关系时,例如使用构造函数,setter,方法。正如在其他答案中已经提到的那样,服务定位器是一种反模式,应该避免使用。原因在this great article

中描述

另一件事是你提到的设置,例如语言或货币,似乎与本地化有关,并且可能更好地处理使用您选择的语言的内置机制(例如资源文件等)。

现在,已经说过,根据代码的其余部分的结构,你有几个选项可以解决这个问题,同时仍然使用服务定位器:

  • 你可以让SqlDataSource依赖于一些从某个地方提取当前语言的ILanguageProvider。但是,如果有更多这样的设置(或者如果难以以一种孤立的方式获取当前语言),这可能会非常快速地变得混乱。
  • 您可以依赖IProductDataSourceFactory(或者,如果您使用的是C#,Func&lt; IProductDataSource&gt;),它将返回具有正确设置的具体实现。同样,您需要能够以孤立的方式获取当前语言才能使用它。
  • 您可以在问题中使用选项1。这将是一个漏洞抽象,但最简单的实现。

但是,如果您决定摆脱服务定位器并开始使用某个DI容器,最好的解决方案是使用选项3(如前所述)并相应地配置容器以提供正确的值。关于如何以优雅的方式做到这一点的一些好主意可以在this question

的答案中找到