如何在基于HTTP头的OWIN环境中配置动态连接字符串?

时间:2016-03-31 18:45:00

标签: c# inversion-of-control owin simple-injector

我是一个使用OWIN和IoC的新手,现在我需要实现一个动态上下文,该上下文由Simple Injector基于HTTP标头解析,该标头标识谁正在调用我的API。这种方法可能不是最好的方法,所以我也愿意接受另一种可能的解决方案。

这是我的OWIN启动课程:

public void Configuration(IAppBuilder app)
{
    var httpConfig = new HttpConfiguration();
    var container = new Container();
    string connectionString = string.Empty;

    container.Options.DefaultScopedLifestyle = new WebApiRequestLifestyle();

    ConfigureOAuthTokenGeneration(app);
    ConfigureOAuthTokenConsumption(app);

    app.Use(async (context, next) => 
    {
        var customHeader = context.Request.Headers.Get("customHeader");
        connectionString = "conStr";//get con based on the header, from a remote DB here
        await next.Invoke();
    });

    app.UseOwinContextInjector(container);

    container.Register<DbContext>(() => new MyDynamicContext(connectionString), 
        Lifestyle.Scoped);
    //container.Register ...;

    container.Verify();

    httpConfig.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);

    ConfigureWebApi(httpConfig);
    app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    app.UseWebApi(httpConfig);
}

我面临的问题是,当DI框架创建实例时,连接字符串始终为空。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

在您的情况下,MyDynamicContext和连接字符串都是运行时值。正如here所解释的那样,不应将运行时数据注入组件中。相反,您应该定义一个抽象,允许在构造对象图之后检索运行时值。

在您的情况下,最好有一个允许检索DbContext的抽象,例如:

public interface IDbContextProvider {
    DbContext Context { get; }
}

DbContext的消费者可以使用IDbContextProvider抽象来获取当前上下文。实现可能如下所示:

class DbContextProvider : IDbContextProvider {
    private readonly Func<DbContext> provider;
    public DbContextProvider(Func<DbContext> provider) { this.provider = provider; }
    public DbContext Context { get { return this.provider(); } }
}

DbContextProvider的注册情况如下:

var provider = new DbContextProvider(() => GetScopedItem(CreateContext));
container.RegisterSingleton<IDbContextProvider>(provider);

static T GetScopedItem<T>(Func<T> valueFactory) where T : class {
    T val = (T)HttpContext.Current.Items[typeof(T).Name];
    if (val == null) HttpContext.Current.Items[typeof(T).Name] = val = valueFactory();
    return val;
}    

static DbContext CreateContext() {
    var header = HttpContext.Request.Headers.Get("custHeader");
    string connectionString = "conStr";//get con based on the header, from a remote DB here
    return new MyDynamicContext(connectionString);
}