Daniel Park
Daniel Park

Reputation: 4021

Injecting into a class library with Ninject, where the constructor takes multiple arguments

I am in the midst of a Ninject dilema. Moreso, how to bind from multiple areas in my C# solution to the same container. In all, I know that loading via Ninject Modules is the best way to do this, but I won't be able to access the kernel directly (which is as I understand it, an Anti-Pattern anyway) to make calls to _kernel.Get<T>().

So it is my belief that constructor injection is the best way to go. Now suppose I have the top level class Program, which loads the Module : NinjectModule class

class Program
{
    IKernel _kernel;
    public static main()
    {
        _kernel = new StandardKernel();
        _kernel.Load(ClassA.Module);
        _kernel.Load(ClassB.Module);

    }
}

To keep code to a minimum, suppose ClassA modules tied all implementations of ISomething to ConcreteSomething, and ClassB (of which ClassA is dependant upon) implements the following constructor method;

public ClassB(ISomething thing, int paramA, int paramB)
{
    //Do stuff with paramA and paramB using thing
}

In a single solution, the _kernel could be accessed directly, and _kernel.Get<ClassB>.WithConstructorArgument("paramA", 123).WithCon...

However, I am uncertain as to how this would work where the providing class has no access to its callers container.

One thought that crossed my mind would be by using a factory method, but I have no idea how this would work.

Any weight would be appreciated.

Upvotes: 1

Views: 391

Answers (1)

BatteryBackupUnit
BatteryBackupUnit

Reputation: 13243

You are correct to use constructor injections for dependencies.

How about moving the parameters (paramA, paramB) to a method, like Initialize or Execute?

If that is not reasonable (like when its command), then you will need to use a factory. Have a look at https://github.com/ninject/ninject.extensions.factory.

For use cases not supported by the factory extension, you can always have a factory which gets IResolutionRoot injected. You can do the Get<> on that interface. The factory can reside in any assembly.

public class FactoryB : IFactoryB {
    private readonly IResolutionRoot resolutionRoot;
    public FactoryB(IResolutionRoot resolutionRoot) {
        this.resolutionRoot = resolutionRoot;
    }

    public IClassB Create(int paramA, int paramB) {
        return this.resolutionRoot.Get<IClassB>(new ConstructorArgument("paramA", paramA), new ConstructorArgument("paramB", paramB));
    }
}

I wonder however, whether you really need to use a factory for paramA, paramB. This dependends on where the values are coming from / how they are determined. Are they dependent upon classA or are they rather just "global configuration" values?

Upvotes: 1

Related Questions