使用StructureMap将同一接口的不同实现注入控制器的最佳方法是什么?

时间:2009-11-10 19:21:20

标签: asp.net-mvc structuremap

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

  1. 按类型(即ObjectFactory.GetInstance<IFoo>()
  2. 按类型和名称(即ObjectFactory.GetNamedInstance<IFoo>("foo.bar")
  3. 我已经看到很多示例演示如何创建一个MVC Controller Factory,它将使用StructureMap提供控制器实例,在大多数情况下我已经看到,他们正在使用上面选项#1中的方法。

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

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

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

    似乎如果使用ObjectFactory.GetInstance()方法,则仅限于为控制器提供存储库接口的单个​​实现。

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

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

1 个答案:

答案 0 :(得分:0)

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

例如,URL /foo/DoSomething可能从ObjectFactory获取IController实例,该实例使用Repository对象进行实例化,该对象使用SqlClient API进行数据访问。然后,诸如/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");