我正在尝试配置一个Web服务,其中我有2个控制器,每个控制器引用一个存储库,该存储库又引用数据库连接上下文。上下文中使用的连接字符串取决于正在使用的控制器。控制器只知道它们各自的存储库,存储库只知道它们的数据库上下文,上下文只知道连接字符串。
如果有一些方法可以知道在InstancePerApiRequest中使用了哪个控制器,我可以在组合根中编写一些逻辑来执行此操作,但这似乎不可能。
由于InstancePerApiControllerType仅适用于支持的服务,我无法做到这一点。
container.Register(c =>
new MyDBContext("my string"))
.InstancePerApiControllerType(typeof(DocumentController))
.As<MyBaseDBContext>();
container.Register(c =>
new MyDBContext("my other string"))
.InstancePerApiControllerType(typeof(WorkflowController))
.As<MyBaseDBContext>();
这是我的设置:
var builder = new ContainerBuilder();
var config = GlobalConfiguration.Configuration;
builder.RegisterHttpRequestMessage(config);
builder.RegisterWebApiFilterProvider(config);
var container = builder.Build();
var configurator = new AutofacConfigurator();
configurator.Configure(builder);
var resolver = new AutofacWebApiDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
// controllers
container.RegisterApiControllers(typeof(DocumentController).Assembly);
container.RegisterApiControllers(typeof(WorkflowController).Assembly);
// wire up context string for each controller here
// document
container.Register(c =>
{
var connectionString = ConfigurationManager.AppSettings[AppSettingsNames.DatabaseConnection];
var newConnectionContext = new SqlServerConnectionContext(connectionString) { ProductID = productId };
newConnectionContext.Open();
return newConnectionContext;
}).InstancePerApiRequest()
.As<ISqlServerConnectionContext>()
.As<IConnectionContext>();
// workflow
container.Register(c =>
{
var connectionString = ConfigurationManager.AppSettings[AppSettingsNames.WorkflowDatabaseConnection];
var newConnectionContext = new SqlServerConnectionContext(connectionString) { ProductID = productId };
newConnectionContext.Open();
return newConnectionContext;
}).InstancePerApiRequest()
.As<ISqlServerConnectionContext>()
.As<IConnectionContext>();
显然,代码总是给我第二个连接字符串,因为它只是覆盖了第一个配置。
我已经开始查看生命周期范围,但是如果它们能够解决这个问题,那么就无法弄清楚如何配置它们以使其工作正常。
我之前使用IHttpControllerActivator
使用Ninject解决了这个问题,该IHttpControllerActivator
在构造函数中占用了一个容器,然后用它来替换数据库上下文对象与使用正确连接字符串的绑定。问题是数据库上下文是从组合根的角度“神奇地”设置的。我希望通过Autofac避免这种情况,但看起来我可能需要探索类似的解决方案。 至少Autofac会让我选择每个控制器有一个试过,无法获得它工作(但?)。interface IController
{
string Go();
}
interface IRepository
{
string Connect();
}
interface IConnection
{
string ConnectionString { get; set; }
}
class ControllerA : IController
{
private IRepository _repository;
public ControllerA(IRepository repository)
{
_repository = repository;
}
public string Go()
{
return "Controller A" + _repository.Connect();
}
}
class ControllerB : IController
{
private IRepository _repository;
public ControllerB(IRepository repository)
{
_repository = repository;
}
public string Go()
{
return "Controller B" + _repository.Connect();
}
}
class RepositoryA : IRepository
{
private IConnection _connection;
public RepositoryA(IConnection connection)
{
_connection = connection;
}
public string Connect()
{
return String.Format("Repository A Connected to {0}", _connection.ConnectionString);
}
}
class RepositoryB : IRepository
{
private IConnection _connection;
public RepositoryB(IConnection connection)
{
_connection = connection;
}
public string Connect()
{
return String.Format("Repository B Connected to {0}", _connection.ConnectionString);
}
}
,使事情更具说明性,而不是在那里有逻辑。
有更好/更简单的方法吗?
更新:
也许这些更简单的类可能会使结构更清晰。在这种情况下,我希望RepositoryA获取ConnectionA并将其注入Controller A,RepositoryB获取ConnectionB并注入ControllerB:
{{1}}