根据活动控制器选择要注入的字符串值

时间:2014-06-20 20:02:11

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

我正在尝试配置一个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}}

0 个答案:

没有答案