Dependency Injection in .NET Core (.NET 6)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
dependency injection is a great way to reduce coupling increase testability and make applications easier to upgrade over time with net core microsoft built dependency injection into the base set of components in this video we're going to look at how to configure and use dependency injection.net 6. look at the various types of scopes why interfaces are important how to update dependencies and more now if you don't know me my name is tim corey it's my goal to make learning c-sharp easier i do this by providing videos here on youtube multiple times per week plus i have a weekly podcast i also provide courses on c-sharp web development and much more at iamtimcorey.com the profits from those sales are what pays the free content here on youtube so that everyone can have a great education in c sharp not just those who can afford it now this video as in most of my videos i'll create some source code if you want to copy that source code use the link in the description all right let's go over to visual studio we're going to create a new project and this is where the first place you need to start talking about where dependency injection is because by default it's in asp.net core project sorry configured set up and ready for you to use in console apps winform apps and wpf apps or desktop type apps it's not set up by a fault you have to actually bring in dependency injection special in order to get it to work it is there and it's available for you to use you just have to know how to configure it if you want to know more about one of those platform types leave a comment down below or better yet go to suggestions.iamtimcory.com leave a suggestion there as to which one you want to see me demonstrate how to add dependency injection into but for us we're going to use an asp.net core web project type and for that where i use blazer server so let's give us a name let's call this dependency injection demo and dependency injection demo app i'll hit create and net six no authentication yes to https no to enable docker and we don't want to check this box here this is for this is a newer box just in case you haven't seen it yet what's for is if you really don't like the top level statements where we don't have the static void main method we don't have the program.cs or program class we just have the program.cs file with the information in if you don't like that you want to see all the boilerplate stuff you can check this box now i prefer the new way of doing things so i'll leave it unchecked but just to know you could go back to the old way if you really wanted to let's hit create once this gets created what we'll do is we'll take out the um let's take out the stuff that's kind of the the boilerplate stuff so we have this data folder here with weather forecast with our forecast service we're going to delete that this is how you set up the template to get rid of the stuff that is just boilerplate you can also delete the fetch data page and come down here program.cs and we're going to get rid of this line right here line 10 where it says add singleton weather forecast service we'll talk about what that even was in a minute and get rid of the top using statements for the data folder which does not exist or data actually it's namespace so we've gotten rid of the web forecast i prefer to do that now we're going to leave the counter page because why not we have a second page but we're just going to focus in on the index page and that's really the only place we're going to spend any time so we're going to talk about configuring our dependency injection now if you're not familiar with dependency injection what it does is it allows us to instead of saying you know create a new instance of a class whenever we want it we can put it into dependency injection and just ask for an instance of that class so let's go ahead and create a class and call it manually to see how we would use not dependency injection but just use it kind of on our own so let's create a class or a folder and we'll call it just logic this is our logic folder inside here we're going to create a class and we'll call this demologic and obviously this is a demo now i want to show you a trick that someone in the comments pointed out forget who it was but really great trick i prefer to have the file scope namespaces now you can use a to config and have them always created that way but if you're in a hurry like i am where you're going to create one or two classes you can still use file scoped name spaces by either going to quick actions refactoring and saying convert to file scope namespace or this is the way that the someone commenter pointed out put a semicolon at the end takes care of it for you i love that that's that's that's great shortcuts right there okay so we'll create a class called demo logic we're going to create two properties value 1 value 2. now these are a bit different we're going to say private set like so which means we need to have constructor c t o r and here we're going to say value one equals and i'll say random dot shared next and let's give it a range of one to one thousand one if you're not familiar with random what does it it gives us a pseudo random number now i've said give me an integer between one and a thousand one but note the reason i said a thousand one is because the top value is excluded meaning we go up to the value right below the top number so we include one but we don't include the top number so this way we can go from one to a thousand there we go and i'm going to copy this and paste it and save for value two as well and this gives me two separate random numbers one for value one one for volume two so in this next just make sure you get the next random number not the same random number okay i'm not gonna you know see the the random value all the rest we don't need to do that this is just a quick demo so with this whenever you instantiate this class you're going to put a value in value 1 and value in value 2 that's random so every time you create a new instance you'll get new values for value one value two they won't be the same as the last values from the last instance you created this will be important so now we have this really crazy business logic which of course is not um it's just a good demo let's go over to the index page on the index page let's clean it up a little bit we'll get rid of the survey prompt and that hello welcome to your new app and we'll leave the hello world there we're going to say at code in the code section we're going to say private demo logic which we need to have a using statement for this which we can do by saying at using dependency injection demo dot logic now i can also if i wanted to i could put it in the imports.razer file and that would apply to all files but i just need to apply to this file so that's that's a way to do that okay and we're going to say let's call it logic we're going to say protected override uninitialized we're not going to do anything async where it's going to do uninitialized and in here i'm going it's instantiate logic equals new so when you initialize this page we're going to get the the value for logic all right we're going to instantiate that one time so this should give us a new instance in this uh this variable every time you load this page and pages don't stay in memory when you go away from them so every time i come back to it i have a new value let's see that in action by coming down here let's say h3 inside here we'll say value one colon at logic dot value one and we'll copy this and paste it down below and yes i'm using h3 just for the sizing purpose this is not how you write good html this is quick and dirty this is just i'm using the the structure elements for styling that's not a a good thing if you want to actually use it correctly you would put probably div with a class of h3 but we're just doing a quick and dirty uh form here so let's launch this as it is so we're not going to do anything else where it's going to launch this page and the first page that comes up is this index.razer page so let's wait for that to load waiting waiting there we go so our values are 9 17 and 180. if i go to counter and come back down to 9 48 and 588 come back again 9 14 488 eight nine three and two eight six so they're different every single time i come to this page that's when i'm creating a new instance every time i come to this page now what are the drawbacks of doing this this equals new this is not dependency injection this is just instantiating a class whenever you need it which seems fine on this one page but what if i have to do in 10 different locations 10 different pages well that's fine i can do it in 10 different locations but now all those pages depend on demo logic they may say okay that's fine but we're not declaring that they depend on demologic anywhere centrally so you might know that buried in the code you know one two three hundred code lines down there is an instant instance of demo logic so you have to figure out where all these dependencies are because imagine if you wanted to change demo logic maybe you wanted to change how it worked but you know what depends on it first to make sure that you change it in all the spots well if i add a better demologic.cs file then i have to go to every different place where this was and change demologic to better demologic and then change all of my other code as well that's how dependencies create tight coupling i'm now coupled to this specific demologic.cs so let's make the coupling a little less by putting it into at least dependency injection we'll get to the the final way of doing this later but for right now we're going to put it into dependency injection how do we do that well we come down here to program.cs and notice right here this is where we configure our services whenever you see the builder.services this means dependency injection our services are our service configuration is where we configure dependency injection and notice we already have some things here we have add razor pages we have add server side blazer so these two methods do more than just one thing they actually add a whole bunch of services into our services so it says is hey we know that you're gonna need a lot of dependencies to run blazer server no problem we can add those in this one method call now we're going to add our own below this so we're going to say actually let's add a using statement first using uh dependency injection demo dot logic like so and now i can say builder dot services dot add transient and we're going to say in the angle brackets it is demo logic like so okay now we're going to talk about add transient in a minute but for now this has added demo logic to our services list which means we can ask for it whenever we need a dependency instead of newing up a dependency or instantiating a dependency like we are here so let's do that here now normally what we do is we just ask for it in the constructor but because this is a blazer server it's a bit different we say at inject we can say i want a demologic instance and let's call it logic now i already have down here this well we don't need to do that and we don't need to do this either the instantiation we just need to ask for logic then we can start using it right here because when we ask for it what's going to happen is it's going to go to our services and say hey services do you have a demologic class and it's going to say yes i do here is an instance of that demo logic it's going to instantiate it for us which this instantiation right here that's handled by dependency injection so we're going to get an instance of demologic so let's run this we've commented out all this code okay we we only have inject demologic logic that's it let's run this again and see if anything has changed all right we have 254 849 so we are getting an instance let's see if it changes yep 258 806 82 545. we can do this all day long and we'll get two different values or different values every single time so we now know we have dependency injection working and that's really all it takes to get dependency injection to work we just put it into we put our instance our class type into the services and then we asked for it that's that's it now let's talk about transient because i said just you know just do this and i'd like to explain why so let's talk about transient when you add a dependency into dependency injection you have three different options when it comes to microsoft's built-in dependency injection which we're using so we have add transient what that means is every time you ask for the item so in this case demologic every time you ask for it you'll get a new instance so every time we say inject demo logic we're going to get a new instance in logic so every time you come to the page we get a new instance that's kind of the default standard of how the the most cases uh for dependency injection are used is we use transit that's the most common because usually you want a new instance every single time now there are other ways of doing this let's say instead of add transient we're going to add singleton now if you're not familiar what singleton is is it is a instance of a class that gets the same instance every single time so when you instantiate a class you usually create a new instance every time well with a singleton you create an instance once and then you use that for entire application everybody uses that so without writing any code that's usually what happens we have to write special code in our class to make it a singleton but with dependency injection we don't have to do that we don't have to write any special code we just have to say i want to be a singleton instead of transient so let's see what this does differently remember i said that you create one instance and then use it repeatedly so we have 154 338 go to counter and come back 154 338 154 338 as many times as we want in fact if we take this url and we go to a new page and paste it in 154 338. so if you were to somehow be on my network and could access my localhost you would get the same value 154 338 every single time so we've created one instance and everybody on the web server uses that same instance so it doesn't matter if you're across the globe you'll get the same instance as everybody else now i do want to pause right here to talk about the the dangers of this the singleton design pattern is one that is overused it is something that people often see and say great this is awesome i can share code among other instances i can share code among guests well yeah you can but that can be a problem because then if you write any data so if i write data to anywhere here well then everyone else has access to that same data and they can change it so usually you don't want to do that with anything where the user can write data or make changes so it's usually for like shared configuration so maybe if you look up information everyone can have access to that same information maybe but even then be very careful because let's talk about connection strings well you can say well i'll get a singleton of that because i don't need to keep looking up the same value over and over again and it's more efficient to have one instance of this class rather than multiple well yes it is but what if different people have different connection strings or same thing with with passwords or anything else be very careful that you don't overuse this the other thing is when i use transient that transient went away when i gained the counter page which means garbage collection can collect it and it can go away with singletons they are in memory for the life of the web server so as long as the web server keeps this this system running those singletons are running as well that memory is constantly in use so that can be problematic too because you know you've got stuff in memory that's lasting forever it's a lot of stuff that can permanently clog your memory up so there is a balance here be careful not to overuse singletons but this is how you very easily create a singleton using dependency injection the coolest part here i wanna make sure i point this out is that we'd have to do anything special to change this from transient to singleton so if you're using demo logic and then realize hey wait we don't need to have all these instances we could use this as a singleton i don't have to change index.razer or any other page or file that depends on demologic i actually come here to one spot and change this from transient to singleton i'm done that's part of the benefit of dependency injection is you have centralized your dependencies and make sure you have the dependencies done once not multiple times so you can say hey you know what we're going to make demo logic a singleton now now there is a another benefit here we haven't really talked about and that is some people look at classes and say hey you know what that data's not changing very often maybe i should make that static a static class instead of a singleton or instead of an instantiate class the there can be reasons to use a static class however more likely that's going to be a bad thing okay so you'd be very careful it's a very small use case to create a static class part of the problem with static class is you can't inherit you can't implement interface because you can't instantiate it you also can't inherit from other classes and use the instantiated parts of those inherited classes so it really limits you to just that one class where it's kind of limited but with a regular class that can be instantiated you can have the same functionality in a singleton as a static class but yeah you can instantiate it you can create an interface and have it implement that interface you can inherit from other classes there's a lot of things you can do because it's a full class that's instantiated or instantiatable so really if you're on the fence between a singleton and static class more likely you probably want to think about a a class a regular class instance that you then put in a dependency injection as a singleton okay so we've got singleton which is one instance for everybody and we have transient which is a new instance every time you ask but there is a middle ground and that is add scoped now what ad scope does is it is a singleton per person so let's see it's an action so it makes a little more sense so we'll launch our web server and i have 818 and 774 still 88 818 and 774 still still still let's copy the url go there again 199 198. that's interesting so we come back over here it's still a 18 74 but over here go off come back on it's still 199 and 198. so each tab which is really a different instance of this blazer server website each instance of this website has its own copy of a singleton so it's only available to this tab this version of a site this version of the site has a different instance so there's two instances right now one for each of these but we're not going to create more unless we add more tabs so if i come keep coming back it's still a a singleton to this particular tab but it's not available to any other tab which means that when i close a tab down let's close them down and i open a new tab back up i now have a new copy this copy is still here so this allows me to kind of release some most resources from the web server when when the connection to that particular client is no longer in use so it's not keeping one instance forever in memory like the singleton is but it is keeping one instance per instance of me talking to the web server which means that i can have load something once per user and then they have act just that user has access to it which means that if we're talking about connection strains or anything else where it might be user specific well that'll be specific to them we don't have to keep loading it over and over again because it's in memory once we keep accessing it so this is kind of nice middle ground when especially a web server where we have the ability to see okay these are different connections to it so scope is kind of middle ground where we have one instance per just that is per connection to the server so uh each tab has its own connection to the server if i went to firefox it'd be a different connection if it went to a different computer and accessed it that'd be a different connection so this allows us to have that that singleton like feel but again be more specific or more localized to where that's available so that's the three different types of service types we can use so there's transient which is the most common that's a new instance every time you ask for it which is what we're used to i mean that's what we're doing here that's a new instance and we just ask for it over and over again every time say new that's a new instance so we're used to that and that's the most common but we can also do scoped which is per connection or per user and then we can do a singleton now i will point out that if you are asking for scoped but you're on desktop client then it's basically a singleton because there's only one client that it's that computer and really at that point there's no way of differentiating multiple people because multiple people have different instances of the application open which will be different uh singletons anyway so just know this is more for the web where you have one website running but multiple users as opposed to the desktop where each user gets a full instance of the application anyway so just note that okay so we have add scoped add singleton and add transient now that's the the three different types we haven't talked about yet is really the common way of adding things to dependency injection and that's through an interface so let's go over here at demo logic i'm going to say right click on here and say quick actions refactoring extract an interface and this interface is just going to have those two values i'll hit ok and now it's implementing the idemologic interface which just has two properties with just getters because actually that's all the interface sees let's put a semicolon here that's all the interface sees is just the get because the interface is not dealing privates so anything public which is just a get all right and it doesn't know about constructors either okay so let's use an interface this idemo logic instead of the actual hard code demo logic over here we can say i demologic like so so there's our interface and our implementation so we're saying is when you ask for an i demo logic give them demo logic all right so now you come over here our index dot razor page we can just ask for i demo logic ask for the interface and we'll get of course logic let's run this and make sure it works as it is there we go our two values still the same because we're still in scoped mode so there's our different values and they keep them okay so that's how you use interfaces they may say well tim why are we ever using interface it seems like it's it's just an extra piece of fluff we don't really need and i would encourage you to not think that way i encourage you to always use an interface with your dependency injection one of the reasons why is because it's very easy then to remove dependencies when we're doing unit testing because again we look at here it's saying rep front this is what i depend on but a unit test doesn't want to test all your dependencies it just wants to test the actual code which of course in our case is nothing but when we test this we can send a different interface a mocked interface instead of the actual demo logic instance to logic that way we can control what the values are now another thing you can do is let's go to our demo logic and we're going to copy this logic for now i'm going to create a a new class i'm going to call it better demo logic grab part semicolon here i'm going to paste in the same code i have to change the constructor but instead of random numbers i'm going to say the first value is 25 and the next value is 50. all right now is this better logic no not really but this one we're gonna put in okay better logic now let's implement the i demo logic interface which just those two properties we're good to go so let's say i wanted to replace everywhere i have this logic right here with better demo logic well with dependency injection i don't have to change any of the places where i have a dependency instead i come over here to program.cs let's change it to add transient that's what it should be normally but instead of saying i demologic gives you demologic it's going to say better demologic with one change i now change my entire application so i know we're only using one place but what if i was using it in a hundred places well i changed it it's one spot and we're done the the upgrade is complete let's run this and see the difference 25 50 every time now yeah that wasn't great and i might say oh you know what that upgrade didn't go well the better demo logic didn't work the way i expected to let's go back to demo logic done let's write it again implemented works okay that's how easy it is to change your dependencies around now you may say yeah but tim how often do we gotta do that let me show you an in a real life instance that you will probably use in the future so let's implement logging now you may say well tim this is about dependency injection not logging yes you're right it is and so we're not going to go deep into logging i have a whole video on youtube on logging i also have um more content in my courses on logging but let's not go too deep into it let's we're going to first talk about where logging is well that comes from right here create builder this implements logging as well as uh sets up your dependency injector container and it sets up your configuration for talking to app settings.json i have a whole course on that um but we're going to use the basics of logging so let's go over to our index page i'm going to say inject ilogger of type index call it logger so this is already in dependency injection so this allows us to log any message we want now i give the type of index because this is the index class and this allows logger to have more information about the the class information it's logging from but let's come down here on our uninitialized we're going to say logger dot log information and we'll say displaying values of value 1 and value 2. and then let's go on a new line here where i say logic dot value 1 and logic dot value two now send a call at the end you may be looking at this and saying team you forgot something you forgot the um the dollar sign beginning here that string interpolation and no i didn't and this is where if you have not really dug into how lighting works in net core you really need to because this is how we can do structured logging so what we've got here is i just have a string but then i have these curly braces which normally we put you know dollar sign in front and now that would be an actual value but notice it's getting it writes quickly these values don't exist because they're actually logic dot value one not just value one but i've put it in clear braces and so what happens is that the log dot log information again log error log critically it's all work the same way when i have curly braces it looks at the very first one and says okay that value must be right after the comma so that value right here the one in the first position so this right here goes to here which i could call it anything i want still works okay because it just corresponds to the first position and this one corresponds to the second position now why do i call it value 1 because when when our logger stores this information it's not going to just store just the string unless that's all it can do it can only store a string like our default logger does in net then it will just store a string so it's just going to store the string where this right here gets replaced with the value of this and this right here gets replaced the value of this however when you have a structured logger it's going to store this string but it's also going to store this value right here separately in a separate column as value as the name value 1. it's going to store the name value 2 with the actual value of this in a separate column that way when you do querying you can query your logs based upon what value one is not try to parse it out of a string which parsing out of a string is a mess so having the value in a separate column makes it much much easier to do querying on your logs to get relevant information so please please please do not use string interpolation when you're doing logging do not put the dollar sign first do it this way instead the dollar sign will force everything to be just a static string which means you won't have this additional information for your structured logger okay that's a bit of a soapbox but that kind of explains why i'm doing it that way so i've got logging involved now as you might imagine we'll put logging throughout our entire application so there will be in a small application you might have a thousand different places where you are writing logging so when you talk about a big application you might have hundreds of thousands of places where you have logging information now we're asking for this from dependency injection and notice we're asking for an i logger an interface let's see where this shows up in our our normal app okay so since i'm using kestrel i get a nice little window over here and notice that we have these two lines here that say that displaying values of 996 and 851 which happen to correspond to 996 and 851 now you may notice actually tim you have two different places yes i do why do i have two different places why do i have it running twice well that's because of how blazer server works and some people say well i need to turn this off now encourage you don't so what happens with blazer server this is another little side here is blazer server actually renders on the server and then it downloads the client so you see an actual value on a screen when you're first looking at it but then it renders a second time to wire up things to be actually interactive so that's why it renders a page twice once to give the user something to see very quickly and a second time to behind the scenes wire things up and get things ready to go for interactivity now yes you can turn it off so you only have client-side rendering in which case it's going to have the page gonna become blank at first until your page downloads and then renders that might be what you have to do but the better option is usually to just have it rendered twice it's okay it actually makes your client experience better which is the point but that being set aside we see now we have our logging now this window right here because of kestrel when you use the iis express you won't see this but this gives us a whole bunch of logging information notice this is all logging information so it comes from microsoft but in here we have from dependency injectiondemo.pages.index we have our logging information so that's great but why am i showing you information about logging well let's close this out and let's think for a minute about what if i wanted to add a a different logger maybe i'm tired of the the basic logger that comes with with depends or with yeah normal dependency injection normal uh asp.net coresight what if i want to change that out for one that's actually more useful because the default one logs to the debug window the console that's about it it's not really useful so maybe i've already injected it everywhere and i go oh no i gotta replace the logger with a real one not a problem so let's go and get a real one let's go dependencies right click say manage nuget packages let's look for ceralog.asp.cor i love ceralog it's a structured logger let's install it i have a video on this as well this i cover sarah long and seek which allows you to store the data and then also have a a web page that gives you a really great way of looking at your logs and actually reading what's going on i encourage you it's a notable aside i encourage you if you log information use it because if you don't use it then get rid of it you're storing information pointlessly and really you're making your life miserable because you're hiding the real messages you want to see with all the fluff of things you don't want to see so use it correctly use these levels correctly as well so normally i don't log at the information level i know i log at the the warning level or higher and then i have information messages in my application so i can change my app settings.json when i'm running in production to turn on more logging if something weird is going on now one more and this is not about logging but i want to make sure that we're clear here one more thing that trips people up is yes you can change your logging level in apps.json people do that and say tim it didn't work well yes it didn't work because you're in development mode and there's a little hidden thing underneath appsettings.json called appsettings.development.json which also has logging information so you can either just delete this and work off of appsettings.json or just know you can change this here for logging locally and then you can change app settings.json for logging in your other environments so just know there's two different places in app settings.development.json overrides appsettings.json okay and i have a whole course about that because just appsettings.json tons of great stuff in there i would encourage you learn that it's really great stuff okay so now i've i've created that that nuget package i've added that one nuget package let's actually use it so back in program.cs where we configure everything guess what we're gonna come down here under the services this is not a service but we're going to say builder dot host dot use ceralog which we have to control dot actually it's not going to work we just do using ceralog top now it's going to configure okay open parentheses twice and say context and config then outside the parentheses put an arrow and curly braces then put a semicolon at the end of all of that come back inside and we're going to say config dot write to console that's it okay that's the basics of configuring sierra log we're gonna use the same console but we've just said don't use the default logger from asp.cor instead use ceralog now notice i did not change anything about my index.razer page it still has ilogger index logger it still has the message everything is still the same i only changed in here to say this overrides the default logger with ceralog instead let's run this okay nothing else has changed okay we're getting values let's open up our our window here looks a lot different doesn't it so a lot more color because it uses things differently and then notice down here i went to that page twice and the first one was 6 18 and 740 the next time was 326 and 484 which is the current one and notice they're a different color that's because of the fact that again ceralog is a structured logger it knows these are separate values now for the console it just prints out the data but if i were to store that in another medium for example in seek or in sql or in a number of other different syncs it can actually capture those as separate values because it knows they're separate values so now we have logging set up in a way that is no longer about the default logger it's about ceralog and yet i didn't change anything about my application i didn't change anything about ilogger but what i did was instead of using the microsoft implementation of the logger i used ceralog's implementation of a logger so it's the equivalent of making up here to this ad transient and saying instead of demo logic we're going to do better demo logic that's the equivalent of what we just did with the loggers and because i changed in one spot it changed for my entire application so that's one of the benefits of using dependency injection now some people ask well what's the difference because i could have said equals new right here as opposed to asking for it up here it seems like it's a a wash it's a symbol same thing the only difference is i'm adding all this work up here and people say it's oh it's all this work to add all of my dependencies in one spot well here's the deal by first of all putting all your dependencies in one spot you are consciously thinking through all the dependencies of your application and then you have a centralized place where you can go and look to see everything your application depends on that's a really good thing because it starts to make you think if you have 500 dependencies you might want to think about can we deal with less dependencies because our application is pretty dependent on a lot of stuff but even if not you've now got a place where you can say here's everything we depend on and then in your application files you right up front say i depend on this and i depend on that so you know exactly what they depend on instead of buried down here you catch oh whoa they depend on demo logic okay so that is a real perk it also makes you think through at the very beginning what do you really depend on for every class if that again that list gets too long maybe it's time that your indication that hey we need to think through this because we've got a lot of dependencies here as well but we also have this nice loose coupling like this where and actually this too where we can change what we're connected to instead of being directly connected to demo logic we're connected to an i demo logic so we can swap out what our coupling is is whether it's the demo logic or better demo logic or whatever same thing with our logging instead of being connected to just microsoft logger we're connected to an eye logger so you can swap out microsoft for ceralog or for log4net or for end log or whatever logging tool you want to create or use from the internet so this allows for this nice decoupled or at least loosely coupled application structure now one question i often get when i do a talk on dependency injection is people ask yes tim but what if i have two different things that both implement the same interface how do i get those independent injection and there's a couple different answers i'm going to show you you know this is what they're asking about they want to do this okay that's the a pretty common ask from people is they want to put two different class instances into under the same interface in dependency injection i'm going to ask you a question i want you to think through your answer here over here let's just say that this does work we can do this over here when i ask for i demo logic which instance is going in here think through it as a compiler not as as the user who knows the answer think through as the compiler which instance you put in here do you put demo logic or better demo logic how would you know and why okay and the answer is you wouldn't know the system doesn't know which one to give because they're both the same so what's going to happen is it's going to give you better demo logic because the last one added so that's probably not ideal so you may say well i want demo logic sometimes and better demo logic other times all right so how do i deal with that well that's when you might either create a different interface for both so i better demo or idemologic and i have better demo logic that might work or you might maybe probably not but you might put just the actual class name in there and ask for the class name but again then you're tightly coupled to those classes or you can leave both of these in and ask for an array in which case you get both of these and then you can figure out which one you want but just be careful because that gets really messy about then you've got hard code places where you say well i want the the type of demo logic but then you're now tight couple the timo logic in that place it's usually ugly usually this is a code smell because what you're doing here is you're saying i have two different classes that do two different things and i want them to have the same interface which yes they can have that but then you probably using that interface in your dependency injection because you have to be able to tell your class this is what i want so there are ways of getting around it again i have a full course on the.net core dependency injection that goes into how to do that and how to differentiate the two and how to ask for both and and so on but i encourage you to think through maybe this is not the right interface maybe use a different interface so you can differentiate the two event that interface just implements the i demo logic interface but it's called i better demologic interface just so that you can then ask for that when asking for better demo logic so just know that by and large you only have one implementation at a time for a given interface it's only in special cases where you might have multiple if you really want multiple to come through so that's something to think through again i cover more of that in the course you really need to go into that and that's kind of like a edge case because in general you'd only have one implementation per interface currently active in dependency injection so that's how you use dependency injection in net core now or net core or net 5 plus which is still.net core where you drop the core name so with this this is built right into asp.net core so if you're using mvc or razer pages or api or blazer server or blazer web assembly this is built right in so you have this automatically for things like wpf and winforms and console apps it's available to you but it's not set up and configured by default same thing with azure functions so you can enable those and let me know again on a suggestion site if you want to see a specific one implemented but this is for all of our web product types just on the other box it's just there we can start using it because microsoft said hey we need this so let's go ahead and implement that and allow you to extend it also note that just like everything else we can instead of using microsoft dependency injection we can actually use a third party dependency injection like auto fact we can replace the microsoft's dependency injection with a third party and still use all of our setup so lots of cool stuff there we can do if we want to grow beyond what microsoft has provided it's provided a really good tool for probably about 90 to 95 of all cases it's just those more advanced and edge case things where you might have to bring in a third party project or if you just like how the third parties do it then by all means use those instead so this is how you use dependency injection that's how to do the various things like scoped versus singleton versus transient how to do things like ask for it in blazer server as opposed to you know if you're in a class like this you just put in the constructor and say i want an i demo logic and i'll give you an instance of it through dependency injection uh one question sometimes comes up is well what if this class depend on well here's a good one i logger demo logic let's call it logger i'll do a control dot here to create and assign the field underscore logger now i can use this logger wherever we want in this class but notice that now this class depends on a class from dependency injection so how do we how does microsoft instantiate this properly well they instantiate it by coming here and saying oh i'm going to need an inter i'm going to need a class instance first so they go out to the logger and say hey let's instantiate you first and then come back and insert that here and instantiate demologic and then they have that instance set up so the the system takes care of that chain of dependencies necessary so it handles all that for us now if you have a class library you can use dependency injection but that will come from your user interface project the actual dependency injection so you will set up dependency injection in your ui project and hand out the dependencies as needed to your class library it's a very good way of doing things because that way your class library doesn't have any hard dependencies it just has the ability to ask for what it needs like like this and then your central dependency injection system in your user interface project will hand down those dependencies as needed now some people ask the question yeah to what if i have a model where is that going here how do you put models in here and the answer is you don't because models are something different they are they're not dependencies they're just data structures essentially and so you don't put models into your dependency injection don't try to there's wacky ways you can try and put them in it just don't do it um so for example i use dapper for creating um a connection between sql and c-sharp very easily and i say hey here's the model name go create one instance of that model per row of data coming back it's going to new up that model it's going to create a new instance of that model to instantiate it so yeah that's going to create a bunch of instances of my model that's okay it's not what depends the injection is designed for it's not a dependency and it doesn't have dependencies which is why you probably shouldn't mix your models with your logic because then you possibly could have dependencies in which case you have a messy setup also we don't pass the the dependency injection system around to our classes we could technically do that and just ask for the dependencies inside there don't do that just ask for what you need so in this case iel logger don't ask for the dependency injection container and then create a logger just ask for a logger all right that way you're not creating tight coupling anywhere so i think that's the big overview again i have a full course there's a lot more detail on this if you really need to have more information but i thought this would be good to show you how the dependency injection system worked so that even without that course you can get the job done with your projects and use them knowing what you're doing not just kind of blindly adding things here and hoping it works all right so that's depends the injection if you have comments thoughts questions leave them down below in the comments i'd love to hear them also if you have suggestions for future content for example uh putting dependency injection wpf app sure or a console app sure we can think about doing that go to the suggestions.iamteamcorey.com site add that suggestion or upvote when it's there i use that site a lot to determine future content of 10 minute trainings of full training of dev question videos also full courses so definitely let me know what you're thinking and hopefully others will also be wanting that same thing and we can we can potentially see that in a future course okay so with that thanks for watching as always i am tim cory [Music] [Applause] you
Info
Channel: IAmTimCorey
Views: 87,850
Rating: undefined out of 5
Keywords: .net, C#, Visual Studio, code, programming, tutorial, training, how to, tim corey, C# course, C# training, C# tutorial, .net core, vs2022, .net 6, dependency injection, c# dependency injection tutorial, c# dependency injection example, asp.net core, c# dependency injection code example
Id: Hhpq7oYcpGE
Channel Id: undefined
Length: 60min 32sec (3632 seconds)
Published: Mon Jun 13 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.