Dependency Injection for Absolute Beginners with C# and .NET

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video i'm going to try and explain to you the core concepts of dependency injection i think you know the core concept is not that complex but it's kind of hard to explain it this way so i'm going to try my best i'm going to show you what it is how to set it up what interfaces have to do with it and what the heck is a container [Music] so at the very core dependency injection is instead of newing up all kinds of classes in in other classes you're going to inject those classes that provide the functionality that is needed into that other class so that sounds a bit abstract hopefully that will all become clear in a minute but just think of this example so instead of we we have a person class right always the person class and we have a logger class so whenever a person is created we want to write a little log message to the console output right so what we're going to do in our person class we have a constructor and inside that constructor we're going to say var logger is new logger and then logger.log and our log message right so that logger is is very specific to that person and suddenly that person is now dependent on that logger class so whenever something changes in that logger class then that also has to change in all the references everywhere right so that is something that we want to change and that is something where we can use dependency injection so if we change this to be like this so we're going to not say far longer is new logger but instead we're going to provide that logger to the person class and suddenly you know we can swap out the implementation um from wherever we create that person so if we create a class where we are doing something from a web application then we can inject that logger with something that writes to i don't know some text file on the uh on the file system maybe because in a web application we are not looking at a console window right and whenever we are running it from our console application then it makes sense to write it to our console app so that makes sense right instead of just having that hard reference in there we are going to inject it so that the caller code can decide which implementation to provide and depending on that it's going to swap out the implementation so when i say injection that sounds like something that is very complex or hard but actually you know it's very simple it's just using concept that you probably already know so you have basically three things you have constructor injection which is you know whenever you do newer by class so you do far through new person then you just have to provide that logger that dependency as a parameter so you could just go to specify it in there it will get that dependency through the constructor and you have constructor injection then the other thing is just you know maybe you're using it in a method level because that method is big and it needs to do a bunch of complex things then you just do the same thing but now you inject it into a method so you just provide that dependency into the method you know if you have a couple of methods that need that same dependency then it might be worth considering doing it in the constructor and you know and not do that thing over and over again injecting it into each method and lastly it can just be a setter so if you just have a property you can just assign the dependency to that property to let the class know like hey here is the thing that can execute the code that you need and you can inject it that way so injecting is nothing else than providing it with the right class to to do certain things and however you do that however you provide that class that dependency to the other object it's all up to you now by doing it this way your code becomes more loosely coupled and more maintainable more reusable because you know you can have a couple of different logger classes and you inject the right one from from wherever you want so you can reuse those components everywhere even in different projects if that's what you want to so that is really really cool and basically that is what this dependency injection stuff is all about um of course you know it's always good to realize if you're just writing a small application just start small start simple right so if your application is going to be short-lived if it's going to be a throwaway if it's going to be a sample it's perfectly fine to have that concrete logger implementation do it that way um no worries but if you're worried about architecture and you want to make your application big or you're going to expect that you know this is the million dollar app it's going to be huge that maybe you want to think about the architecture for a little and that's where dependency injection comes in so right now we've seen this with a concrete implementation but the real power of dependency injection comes whenever we start looking and start adding into the mix interfaces so if you're not familiar with interfaces interfaces basically just define a contract so it just has the method signatures right so it knows you know what the method name is that you have to call upon you know what the parameters are that you have to specify and put in there and you know what's going to be the outcome right because that is what a method signature is you know what it returns you know what it's called and you know what you have to specify and put in there in the parameters so that is really cool but what you don't care about is the implementation of that interface so it can have a million different implementations and you don't care so if we think back to our logging example and our two scenarios we can have a logger that is called the console logger that logs to the console window and we can have a file logger that can write to a file on the file system but they both are defined by the contract that is in ilogger and it will just have that one method which is called log and takes a string message so you know the code that's calling it doesn't care where the log goes it just knows that it can log something and the implementation will figure out how to do that so with these interfaces just defining a contract the loose coupling becomes even more because you know the calling code can now just provide any class that adheres to that interface so if we just look at this one this is the i logger interface in csharpen.net all the interfaces basically start with a i so you know it's an interface so the i logger interface and as long as a class implements that interface that's how it calls whenever they decide to implement that contract then a class implements that interface um so they will implement the actual implementation of that method the log method um and as long as they do that you know you can put that down into our person and it will just be able to call upon that and it doesn't care about the implementation so this makes it even more reusable even more maintainable so that is really really cool and the loose coupling really comes in here so by just injecting this contract in the form of an interface we can still execute the code that we want but it gives us a lot of more advantages of doing it over a concrete class one we can swap out the implementation and that is nice to use for like the file logger or the console logger but what about testing because we all do testing right so whenever you do testing and you want to do unit testing then you might hit functionality that is not available whenever you are in your test run right so maybe you're reaching out to a remote system that is not part of your unit test because you want to test that unit so then we can simply write an implementation for that contract for that interface that is a stub a stub is something that does nothing it will just return some dummy value or you know do whatever you want and whenever we are running our unit tests then we provide our code with that implementation of the code that contract and we can run our code with you know predictable results because we know what that interface will return and that makes it very more testable our code as well so you know what's not to love two you basically only have to ever once new up a class because you know you can just say i want to register this interface with this class and you just say ilogger logger is new console logger and that's the only thing you do and from there you can pass it down into each class and method that you want that wants a instance of the i logger so you only have to new it up once and whenever you decide like hey there is this new fancy new console logger console logger 2 then you can just say in that one line ilogger is new console logger 2 and that is the only line that you need to change as long as that contract that interface remains the same so that means even better maintainability um and you know writing less code i mean who doesn't want that and three we can do the injection automatically what so this is really really cool if you are going to look at like more mature frameworks and whatnot so this is this what i'm telling you right now is all you know free from frameworks and whatever you can write this yourself if you want this is just a concept this is not something that um a framework has invented this is just a concept that you can implement and yes there are frameworks that make it easier for you so another thing i want to add to this concept is containers so a container is nothing more than a runtime object that can register which classes are available for injection in addition it can also resolve things for us so a container is is just a runtime object that basically keeps a list of the things that we register so we can on the one hand say i have the i logger and this is the concrete implementation that goes with it so we can have our i logger with our file logger if we are running in that web context or we have the i logger and the console logger whenever we're running a console app and it basically has that list and you can register all kinds of things kind of a little bit depending on what framework you're using because containers is more like something that is implemented in frameworks again you can write your own if that's what you want but depending on how smart that container is you can do all kinds of crazy stuff with that sometimes the logger is even a interface itself so you know you can swap out the implementation of that as well but that's a little bit more advanced so but if we stick to the very core then you can also register your concrete types in there so you then you're just going to say container dot register person and then we have that person but that person still needs an eye logger right um so and when what we can also then say if you're again if your container is smart enough um it will see that it needs an eye logger and it will go into its bag of concrete implementations and it will find the eye logger implementation for us put that in the person and give you back that whole person so that again that might go a little bit fast i'm going out of my way here but as soon as we go into like the specific frameworks then that will probably become pretty clear pretty soon just remember for now there is a container and it can do all kinds of fancy stuff so i mentioned it already a couple of times there are a lot of awesome frameworks that do all of this and even a lot more so you know let me know in the comments if you want to see more about that see all of this in a context of an actual framework and let me know what that framework is that you're interested in and probably so again you can roll your own you can write this all yourself which is a nice exercise so you know just do the basics and to get the hang of it but you probably want to use one of these more mature frameworks into your application especially if you're going to build something bigger because you know that is just a proven concept it's tested it's battle tested as they call it it's used in a lot of production applications so you probably want to use one of those frameworks and if you're going to use like asp.net and net core then this dependency injection is already something that is built in so that is really really cool again if that's something that you want to see let me know in the comments and i will be making follow-up videos for you on that specific subject now when should you use this when shouldn't you use this as always it depends so you know this is an awesome way to get that separation of concerns so you know each class is just responsible for the thing that they need to do and all the rest is just injected instead of you know hard coded and all these hard kind of references which makes it more reusable maintainable you can easily swap out those implementations so that is really cool also it makes it more testable as i already mentioned because you can easily swap out one of these contracts with like a dummy class that provides you with all your testing needs so there is that as well so then is this all just awesome and there is no downsides well of course there is some disadvantages i think your dependency injection is only as good as your self-discipline um because you know you have to be the one that has to think to yourself like hey this should be an interface which is extra work because before you didn't have to specify that interface and then you have to implement that interface and register it in the container etc etc so there's a couple of extra steps that you might need to do some extra boilerplate code that you need to write which is all worth it for you know because of all the advantages that i've just mentioned but you know it's a little bit more work so you have to have that self-discipline and not just you i mean you're probably working in a team so you also have to make your team aware like hey this is important this is the way that we should do it um and make them aware of the importance of this so um it it really comes down to a little bit of self-discipline to you know keep doing that same thing over and over again and the other thing is it also moves a couple of error messages basically from like compile time to runtime because you know maybe something is going wrong in your interface and that is only discovered like at runtime that something is available that shouldn't be available which is a little bit bit more moved to compile time whenever you are using concrete classes but you know so there's there's always this kind of factor like it depends and um you are the only one who can decide like is dependency injection the thing for me um also another thing that is um heard by you know people who don't like the dependency injection that much is it takes performance hit because if you're going to make everything and everything contracts and interfaces and it has to resolve all these things all the time and by it i mean your application you know each time it has resolves it has to go out and see if it has a registration for that interface come back inject that so you know there's going to be some kind of performance impact if you're going to do this but i think you know you have to write a large application for that to to notice that and it might be you know maybe over complicating things so think of how big your application is going to be and if this is something that is really needed in this video we've learned what dependency injection is how to use it why interfaces are important what a container is so i well i hope you know what dependency injection is right now because i've explained it to the best of my abilities so i don't know what else to do but of course if you have any questions please let me know in the comments i'll be there to answer them in follow-up videos we will probably see a little bit of dependency injection with xamarin forms because you know that's a thing i love so i'm definitely going to record a video on that if you want to see any other videos on like the more mature frameworks maybe that i've already mentioned like how to tiny ioc there's a lot others that i'm forgetting right now but let me know in the comments if you want to see a specific video for a specific concept um to dive into that a little bit deeper or see a specific framework then i'll see what i can do to record a video on that thank you for watching if you've liked this video please click that like button hit that subscribe button to be notified of new content on my channel automatically and i'll be seeing you for my next video
Info
Channel: Gerald Versluis
Views: 27,004
Rating: undefined out of 5
Keywords: c#, dependency injection, dependency injection .net core, c# dependency injection, c# dependency injection explained, c# dependency injection example, c# dependency inversion principle, inversion of control and dependency injection, inversion of control c#, inversion of control explained, .net dependency injection tutorial, dependency injection concept in c#, dependency injection c# for beginners, dependency injection for beginners, c# tutorial, learn c#, c# programming
Id: tTJetZj3vg0
Channel Id: undefined
Length: 17min 1sec (1021 seconds)
Published: Tue Dec 22 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.