如何使用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()”,我开始变得异常说“没有默认构造函数找到”。它根本不会与内核绑定。请你请看看上面的代码,并指出我在哪里出错。

我会感谢您的帮助。提前致谢。

+0

你需要告诉你的容器如何建立你的'DbContext'。我不使用Ninject,但是逻辑就像'kernel。[在寻找TenantDbContext时] [用这个connString使用这个构造函数]' – Jonesopolis

+0

看看[这个答案](https://*.com/questions/35308511/how-to-make-ninject-choose-a-specific-constructor-without-using-injectattribute) – Jonesopolis

+0

感谢Jonesopolis的及时回复。我尝试按照你的建议做如下操作:
'kernel.Bind ()。To ()。WithConstructorArgument(“connString”,“Data Source = something; Initial Catalog = something; uid = something; pwd = something“);'
我知道它错了,只是想检查它是否甚至可以运行。令人惊讶的是它开始执行,但连接字符串没有形成。 – Tarun

您可以添加绑定数据库上下文和指向Ninject使用你的工厂方法:

kernel.Bind<TenantDbContext>().ToMethod(_ => TenantDbContext.Create()); 
+0

谢谢一吨佩特,它只是像老板一样工作。你们有这样清晰的概念。 :) – Tarun

+0

嗨Peit,我想添加另一个ToMethod,但然后NInject停止工作,通过不给予默认的构造函数错误。 ();} 'kernel.Bind ()。ToMethod(_ => TenantDbContext.Create());' 'kernel.Bind ()。ToMethod(__ => MasterDbContext.Create());' – Tarun

+0

It一次只能使用一个“ToMethod”。我怎样才能使用多个“ToMethod”?谢谢! – Tarun