InstancePerApiControllerType无效

时间:2014-07-16 19:48:04

标签: c# asp.net-web-api autofac

我正在尝试使用Autofac配置Web服务,以便为每个控制器映射不同的连接上下文:

// database connections
container.Register(c => new DocumentControllerActivator()).As<IHttpControllerActivator>().InstancePerApiControllerType(typeof(DocumentController));
container.Register(c => new WorkflowControllerActivator()).As<IHttpControllerActivator>().InstancePerApiControllerType(typeof(WorkflowController));

public class WorkflowControllerActivator : IHttpControllerActivator
{
    // snip...
    var connectionString = "workflow connection string";

    var container = new ContainerBuilder();

    container.Register(c =>
    {
        var newConnectionContext = new SqlServerConnectionContext(connectionString) {ProductID = productId};
        newConnectionContext.Open();

        return newConnectionContext;
    }).As<ISqlServerConnectionContext>().As<IConnectionContext>().InstancePerApiRequest();

    var dr = (AutofacWebApiDependencyResolver)GlobalConfiguration.Configuration.DependencyResolver;
    container.Update(dr.Container.ComponentRegistry);

    return (IHttpController)request.GetDependencyScope().GetService(typeof(WorkflowController));
}

DocumentControllerActivator仅在连接字符串中与返回对象类型不同。

[AutofacControllerConfiguration]
public class WorkflowController : ApiController

当我尝试访问该服务时,DocumentController会抛出一个错误,指出“无法将类型为'SearchService.Controllers.WorkflowController'的对象强制转换为'SearchService.Controllers.DocumentController'。”就好像第二个InstancePerApiControllerType注册覆盖了第一个(即它正在为所有控制器执行)。

我出错的任何建议?或者,另一种解决方案? (除了每个控制器中的服务定位器模式。)

1 个答案:

答案 0 :(得分:0)

不确定为什么ControllerActivator方法不起作用,但更简单且更少的web api堆栈特定替代方案可能是:

public interface ISqlServerConnectionContextFactory
{
  ISqlServerConnectionContext Create();
}

// Register this with your ContainerBuilder
public class SqlServerConnectionContextFactory : ISqlServerConnectionContextFactory
{
  private string _connectionString;

  public SqlServerConnectionContextFactory(string connectionString)
  {
    _connectionString = connectionString;  
  }

  public ISqlServerConnectionContext Create()
  {
    var connectionContext = new SqlServerConnectionContext(_connectionString);
    connectionContext.Open();
    return connectionContext;
  }
}

public class MyController : ApiController
{
  private ISqlServerConnectionContext _sqlServerConnectionContext;

  public MyController(Func<string, ISqlServerConnectionContextFactory> connectionFactory)
  {
    _sqlServerConnectionContext = connectionFactory("MyConnectionString");
  }
}

有关AutoFac关系和自动生成的工厂的详细信息,请参阅http://nblumhardt.com/2010/01/the-relationship-zoo/

在这种情况下,当AutoFac容器看到Func参数时,它会传入一个委托,该委托充当工厂方法,返回ISqlServerConnectionContextFactory并将字符串传递给其构造函数。 AutoFac真的很聪明!