Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inject value into injected dependency

I'm having something like this:

class Root
{
    public Root(IDependency dep)
    {}
}
class Dependency:IDependency
{
    public Dependency(int val)
    {}
}

And I'm trying to obtain a reference to Root using ninject. So i configure it like this

var module = new InlineModule(mod => mod.Bind<IDependency>().To<Dependency>());

var kernel = new StandardKernel(module);

I'd like to inject into Dependency some 'val' value that is known only at the moment of obtaining the Root reference from ninject.

What i'd like to do is something like this:

Kernel.Instance.Get<Root>(With.Parameters.ConstructorArgument("val", 12));

Is something like this possible using ninject 1.0?

like image 404
Silviu Avatar asked Jan 28 '10 10:01

Silviu


2 Answers

The Parameters.ConstructorArgument in the context only goes one leve deep by default.

One way of passing parameters down multiple levels is by using a ContextParameter, but something then needs to grab that and say - and now we're going to use that as a ConstructorArgument in this case. One such construct is Providers. See this dojo page for details of Providers

So you can do:

    class DependencyProvider : SimpleProvider<Dependency>
    {
        protected override Dependency CreateInstance( IContext context )
        {
            return new Dependency( (int)context.ParentContext.Parameters.GetOne<ContextVariableParameter>( "masterVal" ).Value );
        }
    }

    public static void Main()
    {
        var module = new InlineModule(
            mod => mod.Bind<IDependency>().ToProvider( new DependencyProvider() )
        );

        var kernel = new StandardKernel( new[  ] {module} );

        Root root = kernel.Get<Root>( With.Parameters.ContextVariable( "masterVal", 12 ) ); 
    }

Or you can manage it as follows:

    class RootProvider : SimpleProvider<Root>
    {
        protected override Root CreateInstance( IContext context )
        {
            return new Root( context.Kernel.Get<Dependency>( With.Parameters.ConstructorArgument("val", ( int )context.Parameters.GetOne<ContextVariableParameter>("masterVal").Value )));
        }
    }

    public static void Main()
    {
        var module = new InlineModule(
            mod => mod.Bind<IDependency>().To<Dependency>(), // Optional if ImplictSelfBinding is on
            mod => mod.Bind<Root>().ToProvider( new RootProvider() )
        );

        var kernel = new StandardKernel( new[] {module} );

        Root root = kernel.Get<Root>( With.Parameters.ContextVariable( "masterVal", 12 ) ); 
    }

While you're thinking about this, consider the points I make in this point re separating the concerns if configuration from object binding in this response.

like image 69
Ruben Bartelink Avatar answered Oct 01 '22 03:10

Ruben Bartelink


With Ninject 3 IParameters (ConstructorArgument is one of them) will now simply be "inherited" to child request when they have ShouldInherit == true (see here).

The solution for this question can now be as simple as:

IResolutionRoot.Get<Root>(new ConstructorArgument("val", 12, true));

where as the true in the ConstructorArguments constructor sets ShouldInherit to true. Also see here

like image 23
BatteryBackupUnit Avatar answered Oct 01 '22 05:10

BatteryBackupUnit