Joh*_*Lee 1 asp.net-mvc connection-string ninject
我有一个使用Ninject连接到单个数据库的MVC应用程序.现在我需要支持多个数据库.目前,我的global.asax.cs文件对ninject有以下定义:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
//Using DI for controllers - use the Ninject custom controller factor
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory()); // Repository config is defined in ninject controller
}
Run Code Online (Sandbox Code Playgroud)
这是我的Ninject控制器类的样子:
public class NinjectControllerFactory : DefaultControllerFactory
{
private IKernel kernel = new StandardKernel(new EriskServices());
protected override IController GetControllerInstance(RequestContext context, Type controllerType)
{
if (controllerType == null)
return null;
return (IController)kernel.Get(controllerType);
}
private class EriskServices : NinjectModule
{
public override void Load()
{
Bind<IRisksRepository>().To<MySql_RisksRepository>()
.WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["mydb1"].ConnectionString);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我还有一个处理用户身份验证的登录页面.它通过LDAP完成,不需要数据库连接.
我的问题是:我可以在用户身份验证登录页面之后绑定ninject connectionString吗?用户将拥有他们想要连接的数据库的下拉列表,例如"mydb1"或"mydb2"或"mydb3".每个连接字符串都将在web.config文件中定义.
请帮忙!谢谢!
不,你不能绑定"之后" - 首先,Web应用程序是无状态的,你无法控制事件的顺序,但更重要的是,Ninject模块定义你的IoC容器,这个配置发生在几乎所有其他的应用程序或请求生命周期.
如果您说用户会从下拉列表中选择此选项,则选择存储库的行为是应用程序逻辑的一部分,而不是IoC配置的一部分.解决这个问题的方法是创建一个工厂界面.实现可以是Ninject内核本身的一个薄包装器.
public interface IRisksRepositoryFactory()
{
IRisksRepository GetRepository(string name);
// Optional: add a GetRepositoryNames() method for populating dropdowns, etc.
}
public class NinjectRisksRepositoryFactory
{
private readonly IKernel kernel;
public NinjectRisksRepositoryFactory(IKernel kernel)
{
if (kernel == null)
throw new ArgumentNullException("kernel");
this.kernel = kernel;
}
public IRisksRepository GetRepository(string name)
{
return kernel.Get<IRisksRepository>(name);
}
}
Run Code Online (Sandbox Code Playgroud)
对于这个特定的实现,您需要确保使用命名绑定(尽管一般来说您也可以使用元数据系统),并明确地执行每个绑定:
Bind<IRisksRepository>()
.To<MySqlRisksRepository>()
.InRequestScope()
.Named("mysql")
.WithConstructorArgument("connectionString", GetConnectionString("mydb1"));
Bind<IRisksRepository>()
.To<OracleRisksRepository>()
.InRequestScope()
.Named("oracle")
.WithConstructorArgument("connectionString", GetConnectionString("ordb1"));
Bind<IRisksRepositoryFactory>()
.To<NinjectRisksRepositoryFactory>();
Run Code Online (Sandbox Code Playgroud)
也可以在不显式创建每个绑定的情况下执行此操作,特别是如果所有目标都是相同类型(即您只有a MySqlRisksRepository
),方法是将连接字符串或相关符号作为参数传递给Get
调用并绑定到上下文方法而不是一种类型 - 但我建议不要这样做,因为就一般情况而言,它真的与当前游泳相抗衡.
还有一件事:不要担心这类似于"服务定位器"反模式,因为就是这样 - 一种肤浅的相似之处.当对象需要能够动态创建依赖项时,建议在IoC容器周围创建专用工厂,因为它可以最大限度地减少单个类的内核暴露,如果切换到不同的框架,可以轻松替换它.
归档时间: |
|
查看次数: |
2984 次 |
最近记录: |