2
votes

I have the following classes (I know they are not well designed; I just want to express the Ninject problem).

I don't know how to pass the constructor arguments down to my service (which is a dependency of Utility which is a dependency of MainProgram):-

class MainProgram
{
    static IKernel kernel;
    static MainProgram mainProgram; 

    Utility Utility;

    static void Main(string[] args)
    {
        kernel = new StandardKernel(new DIModule());

        var constructorArgument1 = new ConstructorArgument("firstArg", args[0]);
        var constructorArgument2 = new ConstructorArgument("secondArg", args[1]);

        mainProgram = kernel.Get<MainProgram>(new IParameter[] { constructorArgument1, constructorArgument2 });
        mainProgram.Utility.ExportToXML();
    }


    public MainProgram(Utility utility)
    {
        this.utility = utility;
    }
}

public class Utility
{
    private IService service;
    public Utility(IService service)
    {
        this.service = service;
    }

    //methods to work with service
}

public class Service : IService 
{
    private readonly string firstArg;
    private readonly string secondArg;

    public Service(string firstArg, string secondArg)
    {
        this.firstArg = firstArg;
        this.secondArg = secondArg;
    }
}


class DIModule : NinjectModule
{
    public override void Load()
    {
        Bind<IService>().To<Service>();
        Bind<Utility>().ToSelf();
        Bind<MainProgram>().ToSelf();
    }
}

The kernel.Get<MainProgram>() fails with the following message:

Error activating string

No matching bindings are available, and the type is not self-bindable.

I understand this is because the constructor arguments are not making their way to the IService.

Is this even the correct approach for resolving my dependencies. I read in a few places that if you use kernel.Get() "you not using DI".

1
I suggest supplying those values as arguments of the ExportToXML. The rule of thumb here is: pass config and compile-time dependencies through the constructor (or property), pass runtime dependencies through methods.Steven
Re not doing DI if you Get, the point is you should have a single Composition Root and it should Resolve a Single thing (with or without using a DI Container) with lots of turtles swimming out from there (which it might repeat lots of times). Run and buy manning.com/seemann and you won't need to listen to hearsay.Ruben Bartelink

1 Answers

2
votes

See "inherited constructor arguments" in this blog post from @Remo Gloor. The shouldInherit argument of the ConstructorArgument ctor needs to be passed true for your case to work.

A word of caution - having magic floating arguments like this is not generally a good idea - if something needs to be passed, pass it and don't confuse matters by using container tricks (i.e. what @Steven said in his comment).

(Also obviously if you can Bind ... WithConstructorArgument, that's much better, but I assume you know that.)

Perhaps you're missing an abstraction - maybe the Service should be asking for a ServiceConfiguration rather than two strings that you can easily get backwards?