1

I am trying to have ninject use a constructor argument from a parent class and pass it as an argument to the child when it is instantiated. How would I do my bindings to make this happen properly? I have been going through the examples and haven't found a solution.

public class MyModule : NinjectModule
{
    public override void Load()
    {
        Bind<ParentClass>().ToSelf();
        Bind<ChildClass>().ToSelf();
    }
}

public class ParentClass
{
    private string _index;
    private ChildClass _childClass;

    public ParentClass(string index, ChildClass childClass)
    {
        _index = index;
        _childClass = childClass;
    }
}

public class ChildClass
{
    private string _index;

    public ChildClass(string index)
    {
        _index = index;
    }

    public string Index { get; set; }
}

var kernel = new StandardKernel(new MyModule());
kernel.Get<ParentClass>(new ConstructorArgument("index", "MyIndex"));

So when I create my ParentClass instance, I want the ChildClass inside to have the same index value.

Greg
  • 7,233
  • 12
  • 42
  • 53

2 Answers2

3

Just change your parameter to be inherited to child requests as follows:

kernel.Get<ParentClass>(new ConstructorArgument("index", "MyIndex", true));

This way the ConstructorArgument applies to all objects instanciated by the Get call. Of course the ConstructorArgument is only applied if there's a constructor parameter with a matching name. In your case the parameters are named index for both ParentClass and ChildClass so it works.

See also documentation of ConstructorArgument constructor here and documentation of IParameter here

Update

In newer Ninject versions there's now the TypeMatchingConstructorArgument which matches for a type instead of a parameter name. However, if it's really a type as ubiquituous as string it makes more sense to "enclose" the configuration value in a new type, as shown by Joseph Evenson's answer.

Community
  • 1
  • 1
BatteryBackupUnit
  • 12,934
  • 1
  • 42
  • 68
2

I was facing a similar problem and initially went with the inherited constructor argument solution until one of my colleagues pointed out the downside - if you (or someone else) ever change the constructor argument name (index) your application will break.

An alternative to using named constructor arguments with inheritance would be to create a configuration type, create a new kernel for this request context and bind the configuration type (for that kernel) to a constant. You'd end up with something like:

public class MyModule : NinjectModule
{
    private string _index;

    public MyModule(string index)
    {
        _index = index;
    }

    public override void Load()
    {
        Bind<ConfigurationType>().ToConstant(new ConfigurationType(_index));
        Bind<ParentClass>().ToSelf();
        Bind<ChildClass>().ToSelf();
    }  
}

public class ParentClass
{
    private string _index;
    private ChildClass _childClass;

    public ParentClass(ConfigurationType configuration, ChildClass childClass)
    {
        _index = configuration.Index;
        _childClass = childClass;
    }
}

public class ChildClass
{
    private string _index;

    public ChildClass(ConfigurationType configuration configuration)
    {
        _index = configuration.Index;
    }

    public string Index { get; set; }
}