我正在尝试使用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注册覆盖了第一个(即它正在为所有控制器执行)。
我出错的任何建议?或者,另一种解决方案? (除了每个控制器中的服务定位器模式。)
答案 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真的很聪明!