我是一个使用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框架创建实例时,连接字符串始终为空。
任何帮助将不胜感激。
答案 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);
}