如何使用Ninject将参数构造函数注入到Repository构造函数中?
问题描述:
我想在运行时通过传递连接字符串来创建DBContect对象。 以下是我的NiNject存储库实现的结构。如何使用Ninject将参数构造函数注入到Repository构造函数中?
public class HomeController : ApiController
{
MyService _service{ get; set; }
public HomeController(MyService service)
{
_service= service;
}
}
public class MyService
{
IRepository _repo { get; set; }
public MyService(IRepository repo)
{
_repo = repo;
}
}
库实现如下:
public interface IRepository
{
TenantDbContext _db { get; set; }
void Add<T>(T entity) where T : class;
void Delete<T>(int id) where T : class;
T Find<T>(int id) where T : class;
IQueryable<T> Query<T>() where T : class;
void SaveChanges();
MasterDbContext _db_master { get; set; }
void Add_Master<T>(T entity) where T : class;
void Delete_Master<T>(int id) where T : class;
T Find_Master<T>(int id) where T : class;
IQueryable<T> Query_Master<T>() where T : class;
void SaveChanges_Master();
}
public class Repository : IRepository
{
public TenantDbContext _db { get; set; }
public MasterDbContext _db_master { get; set; }
public Repository(TenantDbContext db)
{
_db = db;
}
public Repository(MasterDbContext db_master)
{
_db_master = db_master;
}
public IQueryable<T> Query<T>() where T : class
{
return _db.Set<T>().AsQueryable();
}
public IQueryable<T> Query_Master<T>() where T : class
{
return _db_master.Set<T>().AsQueryable();
}
//.....Rest of the implemetation
}
这里去我TenantDBContext类需要一个参数作为数据库字符串。 没有默认构造函数
public class TenantDbContext : DbContext
{
public TenantDbContext(string connString)
: base(connString)
{
//Configuration.AutoDetectChangesEnabled = true;
//Configuration.LazyLoadingEnabled = false;
//Configuration.ProxyCreationEnabled = false; //change tracking
}
public static TenantDbContext Create(string DbString)
{
// Some logic to get the tenant database string.
// Presently i am just passing it hard coded as follows.
return new TenantDbContext(DbString);
}
}
public class MasterDbContext : IdentityDbContext<ApplicationUser>
{
public MasterDbContext() : base("MasterDBConnection", throwIfV1Schema: false)
{
// dbmigration.AutomaticMigrationsEnabled = true;
Configuration.ProxyCreationEnabled = false;
Configuration.LazyLoadingEnabled = false;
}
public static MasterDbContext Create()
{
return new MasterDbContext();
}
//public DbSet<ApplicationUser> ApplicationUsers { get; set; }
public DbSet<Tenant> Tenants { get; set; }
public DbSet<TenantUserMap> TenantUserMaps { get; set; } }
最后,RegisterServices我已经在我的NinjectWebCommons.cs如下所示: 每个租户有其不同的数据库。我们从每个请求中获取访问令牌中的Tenant名称并缓存请求的Tenant对象,以便我们可以传递正确的Tenant数据库字符串,以便对请求的Tenant数据库执行操作。
在下面的代码片段中,我们从当前请求缓存中获取Tenant对象,该对象将向我们提供所请求客户端的租户数据库字符串。
public Tenant Tenant
{
get
{
object multiTenant;
if (!HttpContext.Current.GetOwinContext().Environment.TryGetValue("MultiTenant", out multiTenant))
{
throw new ApplicationException("Could Not Find Tenant");
}
return (Tenant)multiTenant;
}
}
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IRepository>().To<Repository>();
kernel.Bind<TenantDbContext>().ToMethod(_ =>
TenantDbContext.Create(Tenant.DBString));
kernel.Bind<MasterDbContext>().ToMethod(__ => MasterDbContext.Create());
}
问题:当我添加第二次在我的NinjectWebCommons.cs结合“kernel.Bind()”,我开始变得异常说“没有默认构造函数找到”。它根本不会与内核绑定。请你请看看上面的代码,并指出我在哪里出错。
我会感谢您的帮助。提前致谢。
答
您可以添加绑定数据库上下文和指向Ninject使用你的工厂方法:
kernel.Bind<TenantDbContext>().ToMethod(_ => TenantDbContext.Create());
你需要告诉你的容器如何建立你的'DbContext'。我不使用Ninject,但是逻辑就像'kernel。[在寻找TenantDbContext时] [用这个connString使用这个构造函数]' – Jonesopolis
看看[这个答案](https://stackoverflow.com/questions/35308511/how-to-make-ninject-choose-a-specific-constructor-without-using-injectattribute) – Jonesopolis
感谢Jonesopolis的及时回复。我尝试按照你的建议做如下操作:()。To ()。WithConstructorArgument(“connString”,“Data Source = something; Initial Catalog = something; uid = something; pwd = something“);'
'kernel.Bind
我知道它错了,只是想检查它是否甚至可以运行。令人惊讶的是它开始执行,但连接字符串没有形成。 – Tarun