The .NET dependency injection methods you are not using

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody i'm nick and in this video we're going to take a look at some dependency injection methods in the dotnet built-in ioc container that you probably don't know about and you almost definitely not use especially one of them i wouldn't be surprised if 95 of everyone out there doesn't know how exactly it works and why you probably want to use it in this video we're going to recap all the methods in which you can actually register a service and what limitations and what rules you have around those methods if you lack them of content and you want to see more make sure you subscribe during the summer notification bell and for more training check out nickjabsters.com and what a coincidence because i just happen to have a four and a half hour course at nickjabs.com all about dependency injection where i take you through literally everything i mean it is the best dependency injection content you're going to find anywhere so in case you want to grab that i'm going to give you a 20 discount code for the first 50 of you who buy the course use code deps what you see now on your screen all the link in the description to buy the course if you want it all right so let me show you what i have here this is a simple api which has this example controller nothing fancy and then we have a few services here and this just has a single interface and then a couple of implementations of the same interface pretty basic stuff and we're gonna use all of these services as the foundation for what i'm gonna explain in this video so let's say let's start straight away let's say i want to register i service to resolve to service one in a singleton fashion well i have a few ways to do that the simplest one is i can say builder.services.add singleton as you probably know and say i service and then resolve that to service one and then if i am to inject it here i can simply do private read only i service and that will resolve that service what i'm gonna do just so we know exactly what we're resolving and how i'm just going to say get type and then name and i'm going to fire up postman and hit that endpoint all right so if i run this api now real quick and call that endpoint over here then as you can see service one makes sense exactly what we registered now what i want to do is i want to show you what happens if i go ahead and duplicate this line but instead of adding the service one as an implementation i'm also going to add the service to do you know what's going to happen here so what's going to happen here is and let me show you let me just debug this api and go back here so this will now return service 2 which kind of makes you think that by doing that the second one overrides the first one but it's a bit more nuanced than that if you do that and then you try to resolve an individual service then yes the second registered or the last register service is what will be resolved as an implementation but if you go here and you say i innumerable of my service and you try to resolve that and let's quickly do one of those where we do a select and we return an enumerable and i debug this now then as you can see both services are registered it's just that when you resolve an individual one only the second one or only the last one will be resolved so keep that in mind and why should you well when other people register code in their own extension methods when you have like add something or add something else these services might inject things it might register things that you also might go ahead and register and if you have a different implementation you can have problems in the behavior so what some people try to do is to be on the safe side instead of using the add version of the methods and by the way singleton is just one of them you have add transient and add scoped as well and you also have the raw add method which let me just quickly show you um all of that registration in based on the concept of a service descriptor which is a class describing how this service is supposed to be registered so if i say descriptor equals new service descriptor not collection descriptor then i can specify the type of my service and remember services where you're starting implementation is where you're going then i can also specify that i want this to be implemented in the type of service one in singleton fashion and if i do all that then i can go ahead and say builder.services.add and do this and this is usually very good if you want to do any programmatic registration because you can pass the type without having the generic value so this is actually used extensively by libraries as well now all of these add methods work the same however we also had builder.services.try add scoped singleton transient let's leave innumerable outside for now that's a bit different we're going to talk about it but then the rest are effectively the same so you might say try add singleton and i can copy the same behavior and i can take that i'm going to comment this out and then register this and run it and then go here call it and as you can see only one service the service i registered is here however here's what happens if i duplicate this again and i say service 2 with the try add singleton not the add signature if i do that now then as you can see only the first one is registered the second was not registered because a service type of the same type was found to be registered and even though my implementation is different it wouldn't allow me to add anything on top of it so when you use the try methods try add singleton and so on then you will not accidentally add on top of something that is already registered minimizing the risk for unintended behavior and you don't have to worry about multiple registrations now if you want to have multiple registrations then you should go back and use that instead now something i forgot to point out as well is that let's just comment this try and go back to the simple ad if i go back to the simple add methods and i try to add the same service with the same implementation twice then what happens is that you can you can have multiple registrations of the same service meaning now you have two independent singletons which makes them less of a single i mean within their context it's still a singleton but it's no longer singleton effectively so keep that in mind add with multiple calls on the same service will still add individual services risking singletons because they're no longer singletons while this is something that would not happen with the tri methods even if the service is the same i can go ahead run this call it and then again only the first one because that check is here so basically no check here and then check here but here's where the method you probably have never heard of or have never used comes into picture and that method is the builder.services.com add enumerable now what do you think this method is supposed to do because you might say oh i can just pass a list of descriptors and you know if i have a couple of those service one and service two for descriptor 2 and then i can go ahead here and provide some form of array or innumerable and then pass the two down and that kind of tells you yeah you know this compiles this is fine and if i register that these services will be both registered but this is not the only overload you have there in fact you can have an overload that only accepts one even though it is innumerable which is weird in itself because i think many people miss this method because it behaves differently than the triad singleton scoped whatever methods which shouldn't because the name implies otherwise but i digress so you need to know about this one what this will do and let's just to prove that this actually works fine i'm going to just register the first one i'm just going to say try out the numerable and then call that and as you can see service 1 is registered now if i go back and i show you the same example as this one where i try to register two services but of a different implementation so in this case service two is the implementation of the descriptor two then if i do that as you can see it works however if i try to do it again for the third time and register first second and second again then it won't do that so the way this is different than this is that the uniqueness in the try add enumerable method is based on the combination of service type and implementation type while in the try add singleton transient scope or the raw one the uniqueness check is on the service itself making it a very safe thing to use if you care about the uniqueness of the pair so keep that in mind because you cannot really achieve that with any other method unless you write one so to quickly recap let me just uncomment everything and reorganize them a bit just to understand what everything means right so first the add methods the add methods add singleton add transient add scope and add in itself will register the service no matter supplementation type even if it's the same multiple times in most cases it's fine and it's what we use most of the time however you should be careful when you write library code or code other people will use because this could cause problems if overridden by a consumer the triad methods except for the enumerable so try out singleton triad scope triad transient and triad in itself will only check for the uniqueness on the service so even if you try to add the service with a different implementation so service to here not service one then this will not be allowed because it says oh well i have a nice service already i won't accept another one thank you very much no matter the service implementation and then the try add enumerable which is the odd one out will allow you to register the service as long as it doesn't have one in the container with both this service type and this implementation type so this would be registered this would be registered this would not be registered because this one is already in here with this service type and this implementation type and i should point out here that this behavior is also lifetime agnostic meaning that if i had the same service twice over here but with transient and let's say descriptor 2t and i try to register that on top of the previous one which is a singleton then it doesn't matter that the lifetime is different when i call this it still only registers the two meaning that you can have any lifetime you want but as long as the service type and the implementation type already exist you cannot re-register them with this method so keep all that in mind this will change the way you write code if you're using ioc heavily and you're doing some interesting stuff with it and you can learn how to do interesting stuff if you check out my course so i hope you understood everything here because there's quite a lot of play and this relationship between these try ad methods of singleton transient scope and the innumerable can be confusing because in my opinion it implies one thing but it works in a different way well that's all i have for you for this video thank you very much for watching special thanks to my patreons for making videos possible if you want to support this world you're going to find the link in the description down below leave a like if you like this video subscribe welcome like this ring the bell as well and i'll see you in the next video keep coding
Info
Channel: Nick Chapsas
Views: 81,882
Rating: undefined out of 5
Keywords: Elfocrash, elfo, coding, .netcore, dot net, core, C#, how to code, tutorial, development, software engineering, microsoft, microsoft mvp, .net core, nick chapsas, chapsas, dotnet, .net, dependency injection, ioc, inversion of control, di c#, dependency injection c#, dependency injection .net, asp.net core dependency injection, addsingleton, addsingleton vs addscoped vs addtransient, The .NET dependency injection methods you are not using
Id: iQ8cNI7a6mk
Channel Id: undefined
Length: 11min 48sec (708 seconds)
Published: Thu May 19 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.