代码之家  ›  专栏  ›  技术社区  ›  Martin R-L

可以使用约定注入基于ctor参数名称的命名实例吗?

  •  0
  • Martin R-L  · 技术社区  · 12 年前

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

    抄送:

    public HomeController(IQuery getItemByProductNumberQuery, IQuery getCustomerById)
    

    结构映射配置:

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

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

    1 回复  |  直到 12 年前
        1
  •  2
  •   Steven    10 年前

    在我看来,您的代码库中似乎缺少了一个抽象。在正常情况下,服务( IQuery 在你的情况下)应该是明确的,但在你的处境中却不是这样。通过参数名称识别它们通常容易出错,并导致难以维护的DI配置。这并不总是这样(如 this example ),但可能是你的情况。

    要解决此问题,请将 伊拉克 通用接口:

    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一次性实现,但是 this SO question might help 如果没有,使用另一个DI容器可能会产生更好的结果。

    您可以在本文中找到有关为什么要以这种方式对查询建模的更多信息: Meanwhile… on the query side of my architecture