将构造函数参数添加到Ninject绑定

时间:2016-03-17 10:26:36

标签: c# dependency-injection ninject ioc-container

我有一个ASP.MVC项目,我正在使用ninject作为IOC容器。我已将绑定添加为基础结构文件夹中的单独类,如下所示:

public class NinjectControllerFactory : DefaultControllerFactory{

  private readonly IKernel _ninjectKernal;

  public NinjectControllerFactory()
  {
    _ninjectKernal = new StandardKernel();

    PSCCheckContext m = _ninjectKernal.Get<PSCCheckContext>(new IParameter[] 
        { new ConstructorArgument("appNamekey", "Name of Staff Application"), 
            new ConstructorArgument("serverLocationNameKey", "Location of Application Server") });

    AddBindings();
  }

所以你可以看到我正在尝试从PSCCheckContext的构造函数中的web.config设置两个参数。这是另一个处理数据库访问的C#应用​​程序。 AddBindings()类只是按照您的预期将接口类映射到具体实现:

private void AddBindings()
{
  ...
  _ninjectKernal.Bind<IPSCCheckContext>().To<PSCCheckContext>();
}

我遇到的问题是PSCCheckContext类中有2个构造函数,第二个构造函数采用不同的参数:

public class PSCCheckContext : IPSCCheckContext
{
  public PSCCheckContext(string appNamekey, string serverLocationNameKey);
  public PSCCheckContext(string imgNamekey, string imgFlagKey, string serverLocationKeyName);

当我尝试按下Ninject注入此绑定的控制器时,我收到一个错误:

激活字符串时出错。没有匹配的绑定可用,并且该类型不可自我绑定。

激活路径:
3)将依赖字符串注入到PSCCheckContext类型的构造函数的参数imgNamekey中 2)将依赖关系IPSCCheckContext注入到AccountController类型的构造函数的参数pscCheckContext中 1)对AccountController的请求

建议:
1)确保已为字符串定义了绑定 2)如果在模块中定义了绑定,请确保已将模块加载到内核中 3)确保您没有意外创建多个内核 4)如果使用构造函数参数,请确保参数名称与构造函数参数名称匹配 5)如果使用自动模块加载,请确保搜索路径和过滤器正确。

即使我将绑定更改为更好(阅读http://thebrainyprofessionals.com/2013/05/20/passing-constructor-parameters-in-ninject/

IParameter appNamekey = new ConstructorArgument("appNamekey", "Name of Staff Application");
IParameter serverLocationNameKey = new ConstructorArgument("serverLocationNameKey", "Location of Application Server");
_ninjectKernal.Bind<IPSCCheckContext>().To<PSCCheckContext>()
  .WithConstructorArgument(appNamekey)
  .WithConstructorArgument(serverLocationNameKey);

我仍然得到同样的错误。我读过各种SO问题:

Inject value into injected dependency

Creating an instance using Ninject with additional parameters in the constructor

Convention based binding of constructor string arguments with Ninject

但似乎没有人遇到我的问题。

我做错了什么?

我无法删除其他构造函数,因为它位于不同的应用程序中,我认为它正由另一个系统使用。

这是完整性的AccountController构造函数

public class AccountController : BaseController

  private readonly IPSCCheckContext _pscCheckContext;

  public AccountController(IPSCCheckContext pscCheckContext)
  {
    this._pscCheckContext = pscCheckContext;

2 个答案:

答案 0 :(得分:2)

您问题中的代码已损坏。参见:

public NinjectControllerFactory()
{
    _ninjectKernal = new StandardKernel();

    PSCCheckContext m = _ninjectKernal.Get<PSCCheckContext>(new IParameter[] 
        { new ConstructorArgument("appNamekey", "Name of Staff Application"), 
            new ConstructorArgument("serverLocationNameKey", "Location of Application Server") });

    AddBindings();
}

具体做法是:

PSCCheckContext m = _ninjectKernal.Get<PSCCheckContext>(new IParameter[] 
    { new ConstructorArgument("appNamekey", "Name of Staff Application"), 
        new ConstructorArgument("serverLocationNameKey", "Location of Application Server") });

这应该是做什么的? 实际上做什么具有ninject instanciate one PSCheckContext实例,然后它忘记了它。除非PSCCheckContext的ctor对系统有副作用(这不是一个好的编程习惯),否则此代码不会产生任何影响(除了消耗CPU时间和内存)(=&gt;注意{ {1}}是一个局部变量,因此以后无法重复使用。)

我猜你的意思是:

PSCCheckContext m

这会将public NinjectControllerFactory() { _ninjectKernal = new StandardKernel(); _ninjectKernal.Bind<IPSCCheckContext>().To<PSCCheckContext>() .WithConstructorArgument("appNamekey", "Name of Staff Application") .WithConstructorArgument("serverLocationNameKey", "Location of Application Server"); AddBindings(); } 与构造函数参数绑定在一起,这样从现在起它应该可以注入到控制器中。

答案 1 :(得分:0)

您也可以尝试以下方法:

kernel.Bind<IPSCCheckContext>().ToConstructor(ctorArg => new PSCCheckContext(
    "Name of Staff Application", 
    "Location of Application Server"));

WithConstructorArgument相比,我更喜欢这样做,因为如果您更改arg名称,则DI绑定不会中断。