DI和运行时参数 - 结构图

时间:2013-01-15 17:30:11

标签: dependency-injection structuremap

我越来越多地发现自己混合运行时参数和隐式构造注入,这对我来说很难闻。

示例 - 我有一个描述过滤器的基类,以及特定过滤器的各种继承类型(标签,类别,日期,作者等)

var filter = StructureMap.ObjectFactory
.With("caption").EqualTo("Posts filtered by tag:")
.With("parameters").EqualTo(parameters)
.With("displayInSummary").EqualTo(true)
.GetInstance<TagListFilter>();

我这样做的原因是因为在构造函数中我有一个接口,我希望StructureMap能够注入一个具体的类(IArticleConfigurator):

public TagListFilter(string caption, IDictionary<string,string> parameters, bool displayInSummary, IArticleConfigurator configurator)
:base(caption, parameters,displayInSummary, configurator)

但是我刚刚发现我替换了一个简单的构造函数,虽然它是一个具体的类而不是接口,但基本上是相同的东西,但使用DI来注入1个具体类型。我这样做是因为目前我们的配置是在xml文件中,但会被移到CMS,所以使用界面似乎是个好主意。

这似乎是错误的,而不是DI的精神。

我应该使用工厂生成各种过滤器吗?如果是这样,我还可以利用DI获取我的IArticleConfigurator的具体实例吗?

1 个答案:

答案 0 :(得分:1)

您不应将参数明确地从一个依赖项传递到另一个依赖项,或者至少应该最小化它们的数量。使用参数解析实例的一个主要缺点是您将参数名称指定为字符串文字 - 这使得代码在构造函数签名的更改中非常脆弱。

我可能会想到的一个例子(请注意,我对您的域名和实体的责任没有任何线索)是注入提供者,或者如您所说,工厂。例如,创建类似ITagListFilterConfigurationProvider的内容(您应该根据需要更改名称,我只是想提供动力)。如果您对过滤器使用相同的参数,则可以使用以下三种方法创建非常抽象的提供程序,如IFilterConfigurationProvider

interface ITagListFilterConfigurationProvider
{
    string Caption { get; }
    IDictionary<string,string> GetParameters();
    bool IsDisplayInSummary { get; }
}

现在你的构造函数看起来像:

public TagListFilter(ITagListFilterConfigurationProvider configurationProvider, IArticleConfigurator configurator)

您所需要的只是实现它(因为您将具体参数传递给构造函数)并将此行为提取到提供程序。剩下的 - 是使用StructureMap注册具体提供程序并解析过滤器而不传递任何具体参数

var filter = StructureMap.ObjectFactory.GetInstance<TagListFilter>();