【问题标题】:What's the best way to inject different implementations of the same interface in to a controller using StructureMap?使用 StructureMap 将同一接口的不同实现注入控制器的最佳方法是什么?
【发布时间】:2009-11-10 19:21:20
【问题描述】:

我对 StructureMap 相当陌生,但我的理解是有两种方法可以从 ObjectFactory 获取实例:

  1. 按类型(即ObjectFactory.GetInstance<IFoo>()
  2. 按类型和名称(即ObjectFactory.GetNamedInstance<IFoo>("foo.bar")

我已经看到大量示例展示了如何创建一个 MVC 控制器工厂,该工厂将使用 StructureMap 提供控制器实例,并且在我看到的大多数情况下,它们使用的是上面选项 #1 中的方法。

假设我们有一些控制器接受存储库/DAO 接口作为构造函数参数...

public class FooController : Controller
{
  public FooController (IFooRepository fooRepository)
  {
     // constructor code goes here
  }
}

使用接口类使我能够将该接口的任何实现“注入”到我的控制器中。如果对于两个不同的操作,我想注入不同的实现怎么办?也许在一种情况下,我需要一个用于查询 SQL Server 数据库的存储库的实现,而在另一种情况下,我需要一个从 XML 文件或通过 Web 服务调用获取数据的实现。

似乎如果您使用 ObjectFactory.GetInstance() 方法,您将被限制为仅向控制器提供存储库接口的单一实现。

但是,如果您使用命名实例,那么您最终将不得不根据 MVC 框架提供的控制器的名称来创建实例。在大多数情况下,这通常是来自 URL 的控制器名称,但这实际上取决于路由配置。这看起来可能非常混乱,并且只会随着路线数量的增加而变得更加混乱。

是否有任何替代方法可以在不使用命名实例的情况下实现不同的控制器实例化策略?只创建单独的控制器并确保任何给定控制器中的所有操作都对存储库/DAO 类的同一个具体实例有效是不是更好?

【问题讨论】:

    标签: asp.net-mvc structuremap


    【解决方案1】:

    对于它的价值,我最终选择了命名实例,其中每个实例的名称基于 MVC 框架从 URL 中提取的控制器的名称。

    例如,URL /foo/DoSomething 可能会从 ObjectFactory 中获得一个 IController 实例,该实例使用一个使用 SqlClient API 进行数据访问的 Repository 对象进行实例化。然后,/foo.webservice/DoSomething 之类的 URL 将创建同一个具体控制器类的实例,但向该实例的构造函数传递一个存储库对象,该存储库对象使用 Web 服务进行数据访问。

    有几种方法可以覆盖 StructureMap 对构造函数参数的默认自动装配行为。在我的例子中,我使用了 CtorDependencyIs 方法,并且映射看起来像这样......

    // create a named instance for the "foo" controller that uses the SqlClient based repository
    InstanceOf<IController>()
        .Is.OfConcreteType<FooController>()
        .CtorDependency<IFooRepository>()
        .Is(new FooRepositorySql(Constants.FooConnectionString))
        .WithName("foo");
    
    // create a named instance for the "foo.webservice" controller that uses the Web Service based repository
    InstanceOf<IController>()
        .Is.OfConcreteType<FooController>()
        .CtorDependency<IFooRepository>()
        .Is(new FooRepositoryWs(Constants.FooServiceUrl))
        .WithName("foo.webservice");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-20
      • 2019-10-28
      • 1970-01-01
      相关资源
      最近更新 更多