in today's video we're going to talk about dependency injection what dependency injection is what the dependency inversion principle is what the ioc container is what is inversion of control in general by the end of this video not only will you have a deep understanding of dependency injection but you'll also know how it works behind the scenes what are the underlying principles and how you can work with it in your applications my name is Amai and in this channel I talk about software architecture design pattern c. net various other developer tools and just things that you need to know if your software developer and you want to step up your game so if that sounds interesting make sure to smash that subscribe button so you don't miss out on future videos Okay so let's Jump Right In let's start with an example and we'll work our way back to the theory when we look at the examples so let's say that we're an application where at some point in time we need to know how many stars a specific GitHub repository has so let's go ahead and say stars and let's say that to fetch these Stars we're getting it from some GitHub service so as over here we have some GitHub service which has a single method called get Stars which receives over here the repo name let say the repo is called Throw so let's go ahead and generate this class generate this method and let's simplify some things over here so that's a public this returns an INT and over here we have the repo name okay now like in most applications this service won't actually have the implementation details of how to go ahead and call the GitHub API but that will sit in some GitHub client so that's say over here we're simply returning what comes back from the GitHub client when we go ahead and say get repo pass it the repo name and then we can go ahead and access the number of stars specifically for this repository so similarly let's go ahead and create this class create this method let's simplify some things over here let's say public and let's say that this returns a Topp hole of let's say the repo name and also the number of stars then for the implementation we don't really care about this let's say that we have over here the repo name and for the number of stars let's simply say it's the length of the repository name okay so what we currently have is the the following we have the GitHub service that to go ahead and fetch the number of Stars based on the repo name goes ahead and uses some GitHub client which implements going to the GitHub API and fetching the repository details so this entire thing is our application over here we have actually GitHub so the GitHub client is responsible to go to the GitHub API fetch the repo which as inside let's say the repo name and the number of stars and all the other details return this repo back to the GitHub service and finally the gets up service takes the number of stars and returns it to the caller now the underlying pattern that we have over here is very common in backend applications where you have some larger service or component using some client to go ahead and interact with an external dependency but actually this pattern is way more common because if you generalize it then what we have over here we have some large component that uses some smaller component where the smaller component encapsulates let's say calling some API calling a database or a specific computation that's encapsulate ated inside the smaller component and the large component doesn't care about that it's encapsulated in the smaller component and the large component simply uses the smaller component to get the result that it cares about in our case it's the repository so you definitely know what I'm talking about you have this pattern in your application probably all over the place so just take one of the examples in your application your service and just imagine that throughout today's video because this example is very specific but the underlying idea is extremely common so let's talk about some design principles and refactor our code to follow these principles so the first principle I want to talk about is the dependency inversion principle the dependency inversion principle says that higher level components or modules shouldn't depend on lower level components or modules but instead they should rely on abstractions so over here we're not depending on some abstraction but we're depending on the concrete instance of the GitHub client okay and the motivation for this is that with the current implementation what we have is the larger module is dependent on the smaller module and when you have more and more smaller modules you have the larger component with many dependencies and it's coupled directly with all the various implementations of the smaller components so in our example we don't have to have over here a reference to the actual implementation we don't want to depend on that instead we want to depend on some abstraction for example some I GitHub client this I GitHub client interface will have the method get repo that way we're abstracting away the underlying implementation and theoretically we can he an API call working with websockets whatever we want it's hidden behind this abstract component which knows how to return the GitHub repository now this is similar to many other design patterns where you're trying to achieve decoupling between two components so now you're no longer relying directly on the implementation but you can go ahead and swap the G of client from one implementation to another implementation or for testing specifically you can go ahead and swap out the implementation you can do it in different environments it frees the GitHub service from relying on a specific implementation so again the dependency inversion principle what we want to have over here is instead of this we want to have some GitHub client where this GitHub client let's say we have over here some private I GitHub client and this interface exists like this and it has the method get repo which looks like this and our GitHub client is one of the implementations of this interface okay so that's the dependency inversion principle also known as dip now let's talk about what inversion of control is also known as ioc what is the ioc container what is dependency injection also known as di what's the difference between dip ioc ndi and how we can take those principles and everything and apply to the example that we're looking at up until now now real quick before we continue I want to remind you that I have three comprehensive courses on dome train two of them are a Zero to Hero in clean architecture which comprise in my opinion in the most comprehensive course for building production ready applications following clean architecture including test authorization everything you need to know when you're building production applications and also another course on doain Duran design which also I don't think there's another comprehensive course like this course that teaches you everything you need to know to get started with doain and design so all the various terminology various Concepts Core Concepts and principles that you need to know when you're working with doain driven design so if you enjoy these videos you want to expand your knowledge on clean architecture and domain driven design and you want to see more of this on your screen then make sure to check out the link in the description now back to the video okay so let's start with inversion of control so inversion of control is a design principle in which you give some of the control of your system it can be the object it can be portions of your program you give the responsibility the control to some container or a framework so going back to our example we have over here the GitHub service and the GitHub client in procedural programming or just traditional programming we are responsible for writing all the code right and it goes step by step so we go ahead and we create the GitHub service sometime before we call the get Stars method we'll need to somewhere instantiate the GitHub client and everything we need to control the entire process inversion of control is giving some of the responsibility to a framework or a container let's say you're using asp. net you're giving some of the control of the application to the framework you're not responsible for creating the controller when a request arrives you're not responsible for many of the things that the framework is responsible for so in version of control all it is is giving some control over your application over some objects or portions of your program to a framework or a container dependency injection is specifically how do we go ahead and we inject the concrete implementation of this interface to the GitHub service again all dependency injection is is how do we go ahead and set this field over here so you have some field you have some property you have some dependency how do you go ahead and set it now dependency injection is a pattern to implement inversion of control so using some framework or some underlying hidden code you're going ahead and setting the underlying dependencies without having to explicitly go ahead and set everything yourself okay now let's expand a bit more on dependency injection so we have this field over here and we want to go ahead and inject the actual implementation the concrete object to this field there are three types of dependency injection the first one is Constructor injection which is you simply get when instantiating the class you get over here the concrete implementation for this interface and then you go ahead and set it up during the instantiation of the object and then you have to set it and during runtime then you know everything works as expected so again type one is Constructor injection okay so this is the first type the next type is seter injection where you instead of initializing it during instantiation of the object instead you have some Setter method so you have over here something like set GitHub client that receives over here the interface as a parameter and then it goes ahead and it sets the GitHub client to be the GitHub client like so the third type is called interface injection where you basically have some interface let's say it's called I gsub client Setter and this interface has this method like so where the key point in interface injection is that the GitHub service implements some interface over here it's the GitHub client Setter which allows to inject the implementation of the GitHub client so as you can see this is pretty simple in the end what allows you to do is to inject the implementation of the dependency which is the GitHub client now in the net World everyone uses Constructor injection so that's why you'll see in many applications the following patternn where it's basically the first thing that we showed so we have over here the GI of client and we initialize it like so now instead of us maging all the dependencies so for example going over here and saying that the GitHub client is a new GitHub client and then passing it over here instead of us having to manage all the dependency injection in our entire application what you'll often see is that we won't manage it ourselves but instead we'll give the responsibility to some ioc container if you're using net then you'll likely use the following dependency injection ioc container which is called microsoft.
extensions. dependency injection so what we have now is the service collection so we can go ahead and say over here service collection and then we can go ahead and register in the dependency injection IC container what implementation we want for which interface so we can go ahead and say add transient and we'll talk about what Transit means in a minute for now just imagine it that we're adding some mapping in in which we're saying that for the I GitHub client interface we want to have the implementation be the GitHub client class also alongside this let's say that we want to add the GitHub Service as well to the dependency injection I container now we can go ahead and say service collection. build service provider now we have a new object called service provider and the beauty is that now this object controls the creation of the objects and the dependency injection so what we can do is the following we can go ahead and say instead of everything that we have over here we can simply go ahead and say VAR GitHub service and we can say this is a service provider get required service specify that the service that we want is the GitHub service and this will go ahead and create a new GitHub service object which internally already has this set to be the GitHub client which GitHub client this depends on what we defined for the mapping between the interface and the actual object so now all we need to do is go ahead and say GitHub service.
get Stars specify the package that we want dump this to the screen and if we go ahead and say Throw has this many stars and we go ahead and run this then you can see that indeed we use the implementation of the GitHub client as we wired it up in the dependency injection ioc container now just a word on the transient part because there's an entire in-depth video coming on this transient basically says every single time someone needs an i giup client interface go ahead and create a new instance of a GitHub client and use that meaning that over here we're asking for a new GitHub service when we're asking for a new GitHub service the service provider goes ahead and creates a brand new GitHub service why because we specifi that we want it to be transient when it goes ahead and creates the GitHub service then it also needs to go ahead and create the GitHub client because it's one of our dependencies because we defined it as transient as well then it'll go ahead and create a new GitHub client and use that I'll leave it there for now because there's going to be an in-depth video specifically on dependency injection and the various options that we can do in asp.