问题描述
我试图用Autofac配置Web服务,这样我可以映射为每个控制器一个不同的连接上下文:
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));
和
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不同之处仅在连接字符串返回的对象类型。
The DocumentControllerActivator differs only in the connection string the the return object type.
[AutofacControllerConfiguration]
public class WorkflowController : ApiController
当我试图访问的服务,DocumentController抛出一个错误,说无法投型SearchService.Controllers.WorkflowController对象键入'SearchService.Controllers.DocumentController'。这是因为如果第二InstancePerApiControllerType登记覆盖第一个(即,它是做什么的所有控制器)。
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.)
推荐答案
不知道为什么ControllerActivator的做法是不是工作,而是一个更简单,更网页API堆栈特定的替代可能是:
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");
}
}
请参阅
在此情况下,当AutoFac容器看到函数功能参数,它通过在充当返回一个ISqlServerConnectionContextFactory并且通过给它的构造将字符串一个工厂方法的委托。 AutoFac真的是相当聪明!
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!
这篇关于InstancePerApiControllerType不工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!