Dependency Injection with constructor parameters that aren't interfaces

后端 未结 2 1135
無奈伤痛
無奈伤痛 2021-02-03 13:16

I\'m still a newbie at DI, and I am trying to understand if I am thinking of things the wrong way. I am working on a toy problem when I want to represent a Die object that has

相关标签:
2条回答
  • 2021-02-03 13:18

    You could use ConstructorArgument together with Kernel.Get in this particular situation. Here is full sample.

    Module configuration

    public class ExampleKernel : NinjectModule
    {
        public override void Load()
        {
            Bind<IRandomProvider>()
                .To<RandomProvider>();
    
            Bind<Die>()
                .ToSelf()
                .WithConstructorArgument("numSides", 6);
                               //  default value for numSides
        }
    }
    

    Resolving in code

    var d6 = kernel.Get<Die>(); // default numSides value
    var d20 = kernel.Get<Die>(new ConstructorArgument("numSides", 20)); // custom numSides
    
    Assert.That(d6.NumSides == 6);
    Assert.That(d20.NumSides == 20);
    
    0 讨论(0)
  • 2021-02-03 13:36

    An inversion of control container is not a factory. Don't use it to resolve business objects like your Die class. Inversion Of Control is pattern used to let the container take control over the lifetime of your objects. A bonus of that is that it also supports the dependency injection pattern.

    Business objects is typically created, changed and disposed. Hence no need to use the container for them. And as you just noticed, they do take their mandatory parameters in the constructor which makes it hard to use the container for them.

    You can register a DieFactory in the container and let it take the IRandomProvider in the constructor:

    public class DieFactory
    {
        public DieFactory(IRandomProvider provider)
        {}
    
        public Die Create(int numberOfSides)
        {
            return new Die(numberOfSides, _provider);
        }
    }
    

    But it would of course be better to create a factory used to create all related business objects. Then you can take the kernel as a dependency:

    public class AGoodNameFactory
    {
        public DieFactory(IKernel kernel)
        {}
    
        public Die CreateDie(int numberOfSides)
        {
            var provider = _kernel.Resolve<IRandomProvider>();
            return new Die(numberOfSides, provider);
        }
    
        // other factories.
    }
    

    Or you could just take the IRandomProvider as a dependency directly in the class that creates the Die class.

    0 讨论(0)
提交回复
热议问题