0

使用 StructureMap,可以按照约定根据名称注入实例,如下所示:

托儿:

public HomeController(IQuery getItemByProductNumberQuery, IQuery getCustomerById)

结构图配置:

x.For<IQuery>().Add<GetItemByProductNumberQuery>().Named("getItemByProductNumberQuery");
x.For<IQuery>().Add<GetCustomerById>().Named("getCustomerById");

我正在使用遗留代码,因此更改 DI 容器是一项艰巨的任务,但了解其他容器对手头问题的解决方案也会很有趣。

4

1 回答 1

2

在我看来,您的代码库中缺少抽象。在正常情况下,服务(IQuery在您的情况下)应该是明确的,但在您的情况下并非如此。通过参数名称识别它们通常容易出错,并导致难以维护的 DI 配置。这并不总是必须是这种方式(如本例所示),但可能是您的情况。

为了解决这个问题,让你的IQuery界面通用:

public interface IQuery<TParameters, TResult>
{
    TResult Handle(TParameters parameters);
}

这允许您通过其封闭的通用表示来注册此接口的所有实现,并允许您的控件依赖于此封闭的通用表示:

public HomeController(
    IQuery<GetItemByProductNumberParameters, Item> getItemQuery, 
    IQuery<GetCustomerByIdParameters, Customer> getCustomerById)

如您所见,每个查询都定义了一个“XXXParameters”对象。这是一个包含运行查询所需的所有参数的 DTO。您的代码HomeController可能如下所示:

public View Item(int productNumber)
{
    var parameters = new GetItemByProductNumberParameters
    {
        ProductNumber = productNumber,
        // other parameters here
    };

    Item item = this.getItemQuery.Handle(parameters);

    return this.View(item);
}

IQuery<TParameter, TResult>使用 StructureMap 一次性批量注册所有实现可能有点困难,但是这个 SO question 可能会有所帮助。如果没有,使用另一个 DI 容器可能会产生更好的结果。

您可以在本文中找到有关为什么要以这种方式对查询建模的更多信息:同时……在我的架构的查询方面

于 2012-09-18T11:42:49.050 回答