0

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

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

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 的具体实例吗?

4

1 回答 1

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>();
于 2013-01-16T09:17:48.217 回答