InstancePerApiControllerType not working

Deadly 提交于 2019-12-11 13:49:04

问题


I am attempting to configure a web service with Autofac so that I can map a different connection context for each controller:

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

and:

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));
}

The DocumentControllerActivator differs only in the connection string the the return object type.

[AutofacControllerConfiguration]
public class WorkflowController : ApiController

When I attempt to access the service, the DocumentController throws an error saying that "Unable to cast object of type 'SearchService.Controllers.WorkflowController' to type 'SearchService.Controllers.DocumentController'." It's as if the second InstancePerApiControllerType registration is overwriting the first (i.e. it is doing it for all controllers).

Any suggestions where I've gone wrong? Or, an alternate solution? (Other than a service locator pattern in each controller.)


回答1:


Not sure why the ControllerActivator approach isn't working, but a simpler and less web api stack specific alternative could be:

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");
  }
}

See http://nblumhardt.com/2010/01/the-relationship-zoo/ for more information about AutoFac relationships and auto generated factories

In this case, when the AutoFac Container sees the Func parameter, it passes in a delegate that acts as a factory method that returns a ISqlServerConnectionContextFactory and passes the string through to its constructor. AutoFac really is rather clever!



来源:https://stackoverflow.com/questions/24789391/instanceperapicontrollertype-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!