I need more Ninject practical examples

2019-04-06 19:36发布

In the past, I used swiftsuspenders that is an actionscript 3 IoC controller. Basically the first version of switfsuspender had something similar to the Ninject kernel that was called injector.

If I wanted to create an application injector (with let's say the most relevant mappings to be used throughout the application), I had to inject the injector itself in the application classes.

I am wondering now what is the practice to use kernel.get<> among several classes in the application. Should I inject the kernel itself?

Personally I'd rather use kernel.inject but if I can do kernel.inject I can really likely inject the dependencies manually, which is probably better (kiss).

Test cases are nice, but they are far from the real practical issues, so I hope you can help me to clarify this point. Thank you.

Edit: I noticed that some people talk about "root container", It seems like it is the concept I am looking for. How should I setup a root container and let the other application classes know it?

Edit2 Sample code (please forgive errors, it is just for example sake):

class SomeClass
{
    public SomeClass()
    {
        Command cmd = new Command();

        cmd.execute();
    }

}

class SomeOtherClass:ISomeOtherClass
{
 public void allright()
 {
    //right
 }
}

class Command
{
   ISomeOtherClass dependency;

   void execute()
   {
    dependency.allright();
   }

}


Program.Main()
{
    IKernel kernel = new StandardKernel();

    kernel.Bind<SomeClass>().ToSelf().InSingletonScope();
    kernel.Bind<ISomeOtherClass>().To<SomeOtherClass>();

    SomeClass sc = kernel.Get<SomeClass>();
}

I did not test this yet, because I am still fighting with some initialization issues, but my question is, how can the command class know about SomeOtherClass? My current hypothesis is to inject the kernel in SomeClass and use the method Inject.

2条回答
贪生不怕死
2楼-- · 2019-04-06 19:46

Looking at your example, it is clear that SomeClass is not built with Inversion of Control in mind; the tip-off being that it has a dependency on Command, but control of that dependency is maintained inside SomeClass itself. (Command cmd = new Command();)

To invert the control of that dependency, you would need to have a way to inject that dependency into SomeClass. As Remo Gloor has indicated, the standard way of doing that with Ninject is through the constructor.

To do so, you might change SomeClass to something like this:

class SomeClass
{
    private ICommand _command;

    public SomeClass(ICommand injectedCommand)
    {
        _command = injectedCommand;
        _command.execute();
    }

}

Likewise you would need your Command to advertise its dependency:

class Command
{
   private ISomeOtherClass _dependency;

   public Command(ISomeOtherClass injectedSomeOtherClass)
   {
        _dependency = injectedSomeOtherClass;
   {

   void execute()
   {
      _dependency.allright();
   }
}

Then you would register your Command binding in the kernel, perhaps like:

Program.Main()
{
    IKernel kernel = new StandardKernel();

    kernel.Bind<SomeClass>().ToSelf().InSingletonScope();
    kernel.Bind<ICommand>().To<Command>();
    kernel.Bind<ISomeOtherClass>().To<SomeOtherClass>();

    SomeClass sc = kernel.Get<SomeClass>();
}

The kernel would then be able to walk the dependency chain and inject them all.

查看更多
我只想做你的唯一
3楼-- · 2019-04-06 20:07

Use constructor injection wherever possible and Factories whenever there is a good reason not to create the instances together with the object that depend on them.

kernel.Inject should only be used when you are not in change of the creation of the object. E.g. a WebForm

kernel.Get should be used exactly once in your composition root (e.g. Program.Main or MVC3.DependencyResolver) to create your application.

查看更多
登录 后发表回答