如何配置Ninject,使其根据先前注入的实例注入正确的实例
本文关键字:注入 实例 何配置 配置 Ninject | 更新日期: 2023-09-27 17:59:14
我找不到合适的单词来回答我的问题,所以我会让我的代码说话。
我有仓库:
class Repository
{
public Repository(DbContext ctx)
{
}
}
然后我有这个绑定:
Bind<IRepository>().To<Repository>();
Bind<DbContext>().To<UserStoreContext>().When...
Bind<DbContext>().To<CentralStoreContext>().When...
然后我有一个类需要访问数据库的
class Foo
{
public Repository(IRepository userRepo, [CentralStoreAttribute]IRepository centralRepo)
{
}
}
我应该如何配置两个DbContext
绑定,以便将具有正确上下文(基于CentralStoreAttribute)的存储库注入Foo构造函数?
我在概念验证中尝试了这一点,但最终走向了不同的方向。
Bind<IRepository>().ToMethod(x =>
{
var repositoryType = x.Kernel
.Get<IConfigObject>()
.SomeStringPropertyDenotingTheRepository;
switch (repositoryType )
{
case "1": return (IRepository)new Repository1();
default: return (IRepository)new Repository2();
}
}).InRequestScope();
虽然它有效,但我从来没有弄清楚它是在使用IObjectB的单例实例还是实例化一个新实例——不过应该很容易弄清楚。我想每次我在IRepository上使用DI时,它都会调用ToMethod——同样没有经过验证。
使用When(Func<IRequest, bool> condition)
重载检查给定请求或其一个分支r.ParentRequest
的r.Target.IsDefined(typeof(TAttribute), false)
是否为真
我通常创建几个实际上只是别名的类型,而不是依赖于正确位置的属性。这是有用的,因为对于Ninject(以及可能的其他IoC容器),我们通过它们的类型名称来询问依赖关系。
因此,如果你需要能够"请求"一个用户存储库与一个中央存储库,我会创建这样的别名:
interface IRepository { /* methods and properties */ }
interface IUserRepository : IRepository {}
interface ICentralRepository : IRepository {}
class Foo
{
public Foo(IUserRepository userRepo, ICentralRepository centralRepo)
{
// assign to fields
}
}
我更喜欢这样,因为Ninject根本不会渗透到我的应用程序中,它更具声明性,而且我认为它比任何基于约定的属性方法都更容易记住,比如你正在尝试的方法。
Bind<IRepository>().To<Repository>();
Bind<DbContext>().To<CentralStoreContext>()
.When( context => context.Target != null
&& context.Target.GetCustomAttributes( typeof( CentralStoreAttribute ) ) != null );
// make the general binding after the more specific one
Bind<DbContext>().To<UserStoreContext>();