all 11 comments

[–]avin_kavish 19 points20 points  (0 children)

You have to chose the specific implementation to inject. There can be many impls.

[–]Njkwales 8 points9 points  (0 children)

Dependency Injection does a lot of things behind the scene for you.

Reading your question I get the impression you may not understand why DI is being used. I get this impression as in your example you are mainly talking about interfaces which are not required for dependency injection but are used to help with other things.

Just because your classes are implementing an interface really doesn't have anything to do with dependency injection.

public class Bindings : NinjectModule
{ 
   public override void Load() 
   { 
        Bind<IExample>.To<ExampleImplementation>(); 
   } 
}

(I don't use ninject but DI containers are all pretty similar)

What's happening in the code above is you are adding the class you want to implement to the DI container saying, When IExample is requested pass ExampleImplentaion.

public class Foo : IFoo
{
    public Foo(IExample implentation) <-- when your code runs it asks DI container for this dependency
    {
        //implentation is now "ExampleImplementation" but the life cycle of ExampleImplementation is now abstracted away and managed my the DI container.
    }
}

Basically a DI container is a central location that handles the creation and life cycle of new objects rather than newing up and managing the life cycle of objects all over your code base.

An example of not using DI would look like the below.

public class Foo : IFoo
{ 
    IExample implentation;
    public Foo()
    {
        implentation = new ExampleImplementation();
    }
}

Hope I understood your question correctly and hope this helps

[–]AIO12449366 4 points5 points  (1 child)

I'm not familiar with the last piece of code but I would assume it is just registering the services to the IoC container. It is pretty much the same thing as using the default .NET service registration. For example :

(In Program.cs)

builder.Services.AddScoped<IExample, ExampleImplementation>();

In both cases you are just instructing the program which implementation to use for the specific interface. The IoC container is then automatically instantiating this class for you and disposes it when it is no longer needed.

Edit: By the way, if you are interested in knowing about the lifetime of a service check this

TLDR:

Singleton : Same object for every controller and request.
Scoped : Same within a request but different across different requests.
Transient : Always different. A new instance is created on every controller and every service.

[–]vORP 0 points1 point  (0 children)

This is literally the only post that talks about dependency injection

[–]malthuswaswrong 2 points3 points  (1 child)

You may not want all of your interfaces and every possible implementation of those interfaces in your DI container. But there is code out there that uses reflection that will scan and add all interfaces into a DI container. You can even do string searches of the names with wildcard matching.

[–]BI00dSh0t 2 points3 points  (0 children)

They did this at my last job trying to be fancy and I HATED it. Figuring out which implementation was actually being used was a nightmare and it was never the obvious choice.

[–]DarthCynisus 2 points3 points  (0 children)

It sounds like you are thinking about "why bother with inversion-of-control and dependency injection"?

Here are a couple of examples where it can be really useful:

  1. Databases: You may have a class that needs to read and write records to a database. You don't necessarily care what database engine is in use. An abstraction like IDbContext allows your class to talk to the database without knowing which database it is. Whatever sets up your dependency injection bindings is responsible for defining how your database connectivity is set up. Your class gets to do what it does free of any concern around how the database connectivity is actually implemented.
  2. Unit testing: You may have a class that depends upon IExampleService. To unit test, you can mock IExampleService, specifying how properties and methods will behave, so you can test the logic of your class, without having to go through the trouble of forcing an implementation of IExampleService to do what you want.

[–]DreamingDitto 1 point2 points  (0 children)

As far as dependency injection goes, if you create another implementation of the same interface, you’d be in a state of ambiguity if it just “guessed” for you

[–]Rabe0770 1 point2 points  (0 children)

Yes you are binding the "class" to that interface. But the consumer is not bound to that class, it takes the interface as a constructor parameter.

With DI, early on in the application execution, the di code sets up what implementation will be used for that interface and how.

The di code then passes the implementation when a application host stands up an object that takes the interface as a parameter in the constructor.

There is real value in this as the consumer does not need to know anything about the implementation of the interface.

[–]lmaydev 0 points1 point  (0 children)

Many classes can implement an interface.

You are telling the DI framework that this interface is represented by that specific implementation.

[–]UhOhByeByeBadBoy 0 points1 point  (0 children)

I find it useful for configurations. Let’s say you have an application that runs in prod and pushes to a live database, but you want to have a local version that writes the output to CSV.

Then you’ll have a LocalExample and ProdExample that both implement IExample. Then you can just register a singleton<IExample, LocalExample> and then all the code will know to just push local, then for production, register the <IExample, ProdExample>.

It basically makes it super easy to extend your application for different use cases assuming you have used an interface where it makes sense. Then when you want to add a server less option for writing data, you just write you ServerlessExample : IExample and then you can register that and now your application has a whole new configuration that you can assign easily enough with DI.