Search code examples
c#ninjectdependency-management

Combining DI with constructor parameters?


How do I combine constructor injection with "manual" constructor parameters? ie.

public class SomeObject
{
    public SomeObject(IService service, float someValue)
    {
    }
}

Where IService should be resolved/injected by my DI container, and someValue should be specified. How do I mix the two?


Solution

  • Such constructs should be avoided whenever possible. Therefore, ask yourself: is this parameter really required as constructor argument? Or can SomeObject be replaced by a stateless one which is reused by everyone that depends on it by passing the parameter to the method you execute on the object?

    e.g. Instead of

    public class SomeObject
    {
        private float someValue
        public SomeObject(IService service, float someValue)
        {
            this.someValue = someValue
        }
    
        public float Do(float x)
        {
            return this.Service.Get(this.someValue) * x;
        }
    }
    

    use

    public class SomeObject
    {
        public SomeObject(IService service)
        {
        }
    
        public float Do(float x, float someValue)
        {
            return this.Service.Get(someValue) * x;
        }
    }
    

    If it is required go for a factory:

    public interface ISomeObjectFactory
    {
        ISomeObject CreateSomeObject(float someValue);
    }
    
    public class SomeObjectFactory : ISomeObjectFactory
    {
        private IKernel kernel;
        public SomeObjectFactory(IKernel kernel) 
        {
            this.Kernel = kernel;
        }
    
        public ISomeObject Create(float someValue)
        {
            return this.kernel.Get<ISomeObject>(WithConstructorArgument("someValue", someValue);
        }
    }
    

    Preview: Ninject 2.4 won't require the implementation anymore but allow

    kernel.Bind<ISomeObjectFactory>().ToFactory();  // or maybe .AsFactory();