C# Web Application Activity 7 Dependency Injection Inversion of Control Principle

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hi in this video we're going to do an introduction to dependency injection and then we're going to create two projects that will demonstrate how it works so first of all let's talk about what dependency injection is and why you would care about it if you're a programmer so dependency injection is a common programming technique that is used in projects that have lots of different modules the idea is to make the modules that you create more independent of each other less rigid and so it's to make things better and more maintainable so the three things that i can think of of why you would want to use dependency injection is that your classes become more reusable so if you're in a team and you have projects that are going to be adopted somewhere else you can save a lot of money by reusing your project they're more testable so if you try to run a test against something that is very complex it becomes very difficult and of course rigidity is something that is bad when it comes to reusability i'll give you an example of what this all means so that way it doesn't sound so abstract so let's take a look at two examples of a car so the top one is your typical car that you would create in a class in a course like a university let's make a car let's say and let's give it some wheels maybe four wheels maybe more and then we'll have a motor and so we instantiate these things inside the class we say let's create a new motor and you just new it up you create a new instance of it so that is a has is relationship or has a has a relationship now the code that you're going to see in the examples is going to look more like the reddish pink one below where instead of saying let's make a new list and make a new motor we're going to put in the interface for motor or an interface for a wheel inside of the type now it looks like a small difference but when you put in an interface it allows you to substitute different kinds of wheels let's say we had goodyear tires or firestone tires or off-road tires or racing slicks these tires then become interchangeable on your car and i guess the engine would be too maybe not quite as easily swapped out in real life but the idea is that we're going to have more swappable components and this will be important when it comes to building things like data access or loggers or other types of items that are less tightly coupled to your application so here's a simple rule if you want to follow a dependency injection a quote when you're writing a definition of a new class never instantiate anything inside of it so unfortunately most of the code examples that you see from me do exactly this we instantiate things inside it for instance we say we need a new repository for the data we just say equals new data repository and away we go so it's simple to code but then it becomes less flexible in the future so here's an example so we have a a method here or a class called get input the first line there where it says get or data getter and we got a new instance of it there it is that's the new instance of it and we're going to try to avoid this when we use dependency injection so let's remind ourselves of some principles called solid programming s-o-l-i-d so solid means s make your code to have a single purpose for each module for example this knife here can do 80 different things we would rather have 80 different knives and that way we don't have to carry around this massive switchblade now a single responsibility would be for example if your game is to have a score keeping module you don't make the module say update the score check for a game win and print it to the screen that's three different cases we want to split that up another is to have a principle called open closed and the idea here is that if you have a module that you want to expand you extend it you don't go in and modify the original and the idea is that you when you're building an architect plan for a building that you have it extensible so that way you can just knock a wall out and add a new room rather than tearing the house down and rebuilding it another is the liskoff substitution which is kind of a little more complex and by the way this uh you can watch all these principles on a longer explanation on a different video that i have but a a descendant class of something should not be something that would break the original for example if you have a car you would not descend into a child to be a helicopter you would want to design it rather to have a general vehicle and then make that the parent another is to have interface segregation so and we've all had an interface where we have these adaptable uh cables they're very handy because you just need one cable but they're also very awkward because you might have in this case eight different ends to it the last one here that we're talking about is called dependency inversion it's one of the five solid principles of programming and think of a dremel a dremel is a tool that simply has a spinning axle and you can attach things to it you can make it into a drill a sander a grinder a small saw it does a lots of different things and the idea is that the drill bit is going to be interchangeable and so that's the analogy that we're trying to do here with dependency injection we have an interface for example give me data and then the data can be different types of data so the inversion of control is a principle that we're talking about here so dependencies are injected injected means they're just passed in as a parameter rather than hard coded in and then we can take away the that dependency we want to do this because it makes the code maintainable easily updated and testable so the object coupling is bound when you run the program through a configuration file and the com the components then are linked together so some examples that you would use this with such as if you have a logging program and we've done logging in the previous lessons what happens if we didn't want to use the library called n log we wanted to use a different one well dependency injection would allow you to change it out without modifying your original code business services and data access services are two other examples and we're going to demonstrate a data access service if you may recall in this course that we're teaching right now the data access that we have has two different forms we have one that connects to a database a sql database and then we also created another data access for products just straight from a text file that was very static and so we're going to demonstrate how we can substitute one of those data sources for the other with a single line of code so that fits right into the idea of having fake data versus real data so if you want to do some testing on fake data then you can and real data when you need to so there are three ways that you can use injections into code one is called the constructor the other is through a property and the other is through a method parameter so we're going to demonstrate with this first one here called the constructor you can see the example of a constructor of a program here called test logging service controller and it is asking for a parameter called service notice the type of the parameter doesn't say data service as its data type it says i logger and so that means it's an interface and so you can have one or more different types of services passed in here and the configuration file an external file will determine which one of those things it'll be secondly there's another syntax that you would do it's called it's called a implementation of a class property and you can put in a square bracket and put the word dependency and it'll work just fine and the other is a method parameter which is very similar so we're going to demonstrate the first of these three examples so the re is so the recipe to make this is to create a service first of all and then it has an interface so that means there's more than one version of your service and then you have to make sure that those are both conforming to the plan that was in the interface and then here's the configuration file what it's going to look like literally we're going to say we have a paired up association going on for instance if we have a logger called my logger 2 it is going to be paired with this interface called i logger and literally we would just go in and change this line if we wanted to change the data source for our application so two examples that we're going to code here one we're going to make a console app which will take away all of the complexities of the web application and we'll just make a simple game with heroes and weapons and then we'll go back to our products application that we have done in previous tutorials and we'll swap out the data source so you can see how easy it is to change from test data to production data in a real class okay so let's get started with coding of our first example so the first thing i want to do is start up visual studio and create a new project i'm going to select a console version and let's call this thing a video game dependency example the first thing i'm going to do is create an interface for one of our game objects let's call it a weapon so i weapon is the object name and you notice it's an interface also let's give it a method let's say attack with me is what any weapon can do let's also define an interface for our characters in our game we'll call them heroes so the interface will be called i hero and his action well hey one thing the hero can attack next let's actually create a class and we'll call this thing sword so we will give the sword one property and it will be a string we'll call it sword name so now let's go ahead and implement the i weapon interface because that's what it is it's sword as a weapon so when we choose i interface as the thing that we're implementing you'll get the red underline that says you must implement this method and so we do so attack with me then becomes something that we must program it's part of the interface and for this guy let's just say the console right is our message and we're going to say the sword name slices through the air devastating all enemies so put some kind of a string in here to let you know that you're using the sword now let's make a hero so i'm going to right click and choose add item i'm going to name my class as hero that only uses swords and so we're going to we're going to program this one very statically he will not have the ability to switch weapons and the property that we'll give him is a name so let's choose string and name for the property so now i'm going to create a method called attack and all it will do is print a message but i'm going to make sure that i do it wrong let's say quote wrong what i'm going to do is instantiate the sword inside of this method and so we'll say we'll do it wrong the first time we will demonst later we'll demonstrate the dependency injection so when you in when you create a new sword or a new object inside of a class that means that the class has now a strong dependency on its on its objects that it possesses and so it cannot exist unless that sword also exists and so that's what we're trying to demonstrate here so the code to make this happen we're going to instantiate a new sword here so we'll say sword equals a new sword and let's give the sword name excalibur and then we will console right out to say that this person prepares himself for the battle and then we use the sword attack method attack with me so the demonstration here is that the sword now is instantiated inside of this attack method so imagine now that this sword is no longer needed and the hero wants a gun sorry you're stuck with a sword we've coded it in it's static it's inflexible so now let's go into the program cs this is where the main action happens and we will instantiate a new hero we'll call him hero1 and he's of type hero that uses only swords we'll give him a name called ultraman and then we will make him attack and then finally we'll add a console read line so that way we'll see the message before the console window closes let's run this and see what happens so hopefully this does not shock you what the results are we get a message that says ultraman prepares himself for battle excalibur slices through the air devastating all enemies so so far this is pretty normal looking we haven't done any dependency injection yet we've just demonstrated that this sword and the hero are welded together in the code you really cannot separate them anymore now let's make a new weapon we'll call this thing a new class and then the name will be grenade so grenade will have a single property called name and then let's implement the i weapon interface since we can attack with it we will then have to implement the method and we will have the method called attack with me so very similar to the sword but now the method will just be slightly different in how the weapon works so now for the print message for our attack we'll say name sizzles for a moment and then explodes in a shower of deadly metal fragments now we're going to demonstrate a new hero that can use any weapon so let's do a right-click and choose a new class and let's name this thing hero that can use any weapon for his properties let's give him a name which is a string and then the second property we'll call this thing his uh typos i weapon so it's an interface and we'll give the object or the property name as my weapon so you can see right away now that this is no longer a going to be fixed to a sword or a grenade it could be either or because they're both of type i weapon so now let's turn this hero into something that implements the ihero interface so we have to implement the methods which is going to be attack it appears that heroes can attack and that's their only purpose so let's put in a console right that says name prepares to attack and then we'll take his weapon and i use the method called attack with me next let's create a new hero we'll call him hero2 and his type is going to be a hero that can use any weapon and when we create him we will instantiate him as his name will be aragon let's say his weapon of course has to be a sword so we will make new or my weapon to be equal a new sword and let's call this sword brissinger then we can make hero2 do his attack routine and let's put in a console right just to separate him from whatever comes next now the third hero that we're going to make is going to also use any kind of weapon so his type is hero that can use any weapon we'll call him hero3 for his instantiated values uh let's give him the name of the joker which is kind of debatable whether he's a hero or not but let's give him a new weapon and since he is the type of hero that can use any weapon we could put sword here or we have another option now called the grenade and we'll give his name the pineapple so let's print out his messages and let's run the program so the application ran and let's see what we got so first of all ultraman uses his sword and then aragon also uses a sword so so they seem to be indistinguishable but the second type of hero that can use any weapon can also have a grenade and so you can see that the joker now uses his grenade called the pineapple and so we're just demonstrating here that the fact that an interface can be used to swap out the weapon of the hero so this is going to i go somewhere i promise this is going to show what dependency injection will work with in just a few minutes now let's carry this example a little bit further with dependencies we're going to make a gun and bullets so let's first of all define a type of bullet so the bullet class will have two properties we'll give it the string as a name and then an integer as the amount of powder that the bullet contains so grams of powder is a good name okay now let's generate another weapon so i'm going to create a new class and this class will be called gun the gun will have two properties the first one will be a string which is his name not surprising similar to the other weapons and this one's going to be different though because he is going to have another property of a type list a list of bullets and so the bullets can be loaded or unloaded so we need to implement the iweapon interface if we're going to make it a true weapon the weapon interface says we are going to implement the method called attack now in this case we're going to have a little bit different type of attack we're going to check first to see if there are any bullets in the gun so if the bullet's counts is greater than zero then we will fire a bullet and firing a bullet means do a console right it'll say the name of this weapon fires around called and then the bullets each have their own name so we will call the name of the bullet and now they will say the victim has a deadly hole in him and then we'll do a console we'll have to we'll have to remove the bullet from the gun then since it's been fired and if there are no bullets then we will have an else statement and the else statement will say the gun has no bullets nothing happens and so take a second here to review all the code that we're writing here this gun has two properties a name and a list of bullets and then the attack method will check to see if a bullet is in the gun and remove it when it is fired so now let's go ahead and create an instance of this new hero so he's going to be called hero4 he is of type that can use any weapon so let's make his instance to say the name is g.i joe he's going to have a new weapon which is a gun and the gun will call it six shooter and then we have to create a new list of bullets so the bullet is a or a list of bullets is a new list and then we've got ourselves the uh the task of defining all of those bullets so the first bullet we'll call as silver slug and he will have 10 grams of powder now i'm going to copy and paste these bullets so that way i have less typing to do so the second bullet i will name as lead ball and give him some number of grams the third one i'm going to call rusty nail and also update his grams of powder and then the last is the called the hollow point all right so now we've got a kind of a confusion of all of these uh parentheses and brackets let's see if we can fix some of these so i'm not sure if i got the right number or not also look up at the the list itself has to be using uh collections let's see if we make that oh my goodness uh we've got lots of uh brackets here let's see i probably need a semicolon after this one and my code is reformatted i believe that looks more like it so i'm just going to line things up so that they look nice and more readable and maybe do some indenting so that way it looks like one belongs to the other okay so clean up your code so that it looks something like this here we've got a new gi joe his six shooter gun has four bullets in it and each of those bullets has a name so pause if you need to to check this out now let's go ahead and make him fire his gun so i'm going to make gi joe attack so hero4 dot attack is the method and since we're checking to see if he has lots of bullets in his gun we should fire more than four times so we'll copy and paste let's run this and see what kind of results come out so sure enough we have results for gi joe as well it tells us exactly which bullet was fired so for instance it says the first round is the silver slug and the second one is lead ball then rusty nail then hollow point and then finally it says the gun has no bullets all right let's get to the dependency injection part of our tutorial and see what all of this nonsense is supposed to demonstrate so consider a minute here that two heroes that i've just created in this diagram so hero 1 has a gun hero 2 has a sword both of these are pointing to an eye weapon interface and so if we were to change some configuration we could tell the heroes now that instead of an eye weapon being a gun it could turn into a grenade or something else so to use this new dependency injection idea we're going to go into the dependencies of our project itself so right click on the project and choose new get and manage extensions with new get so we're going to browse for different things that we can add to our project and i'm going to search for the word depend and what i'm looking for is microsoft extensions dependency injection and we'll choose the install method so now we can close the project dependency managers so now let's switch into the program.cs and scroll down to the bottom where we've been doing our different heroes so what we're going to code next is like a configuration file and so i'm going to put some comments in here to let you know that in asp.net this kind of work happens not in program cs but in a config file so we'll be doing that slightly different in the next example so in this section here we're going to create what's called a service collection so service collections are what are considered a quote container a container will be like a box that contains a list of all registered dependencies so service collection is the class type the instance is services and we'll just create a new instance of it so the next section down is going to associate what each weapon will be by default so i'm going to use grenade for example as the default new weapon to make that happen i type in services dot add transient so transient means it's temporary and i'm going to associate two things so i weapon comma and then the weapon type that all new weapons will be so in this case grenade following this pair of associations i'm going to create a small function that will just generate a new grenade so i'll say grenade arrow function equals new grenade and the name i'm going to call by default is exploding pen and it looks like i forgot to make the arrow actually an arrow so let's fix that next i'm going to define all of the heroes to be a hero that can use any kind of a weapon and i'm going to name him johnny by default so we'll do services dot add transient and then the two different associations again so i hero is going to be associated with a weapon or the hero that can use any type of weapon and then we're going to have a little function that runs after this that will let us create an actual instance of it so we'll say hero arrow function equals a new hero that can use any weapons and his name will be called johnny english by default now the catchy part is what's his weapon going to be so we are going to say his my weapon is going to be equal to hero looks like i need to change it from hero1 to the word hero hero dot get services or get service and then whatever weapon was already assigned so this depends on the lines that were just defined before here then we need parentheses and a closed bracket and a parentheses again and a semicolon wow we got all those syntactical things going on but when we're done here we're going to say that all i heroes are going to become johnny english now lastly there's somewhat of a compile step or an assembly step that we're going to create that will define everything above and put it into one package so it's called a service provider and we'll name it as provider and it's going to use the services dot function called build service provider and so it will define all these associations in one package okay finally we get to the end where we can implement this thing so let's create a new object and we're going to just say his type is var because it could be flexible so his name is hero5 to get his definition we're going to say let's go to the provider object and say get the service of whatever i hero currently is defined as and then we're going to implement it so we'll test it out with uh the hero5.attack method and then put a right line and then finally we're done okay so all of that gives us some flexibility to say what hero 5 is going to look like right now he should show up as johnny english let's run it and test and see what happens okay so you can see all the four heroes were no changes but then the last item down here at the bottom we see johnny english now is hero5 and he has an exploding pen which is really a grenade now all of this coding comes down to one advantage that we're going to demonstrate here we're going to change out the weapon without actually changing any of the constructor so let's comment out the current process that associates a weapon with the grenade and now we're going to make a new item so we'll copy and paste so the new item is going to be of type sword and the sword let's call it as the name is the sword of gryffindor now you can see that there is a message that says there's a problem with this uh don't i have sword as the name let's check to see what the solutions are oh it does say sword name is actually the property in your in your class okay so sword name let's uh see what happens here now so johnny english should now have a sword in his hand instead of a grenade and so now we look down at the last item it says johnny english appears to attack and he does have a sword in his hand instead of their grenade so we did a swap out using this configuration of the dependencies all right so now i'm going to see if we can trust johnny english with a gun so let's go to the dependency and i'm going to copy and paste the definition for a gun and his four bullets and i'm going to put them in where the sword definition was so looks like i have a few fix-ups here to do but the type gun is now associated with iweapon and so johnny should have a gun in his hand i'm going to run the application and see if it works so it looks like i've got the application running and six shooter is in johnny english's hand and he shoots and there's a bullet hole in the victim i would only shot one bullet so let's go back and see if we can make johnny attack a few more times so i'm going to copy and paste a few more attacks for 5 and run it again and this time we should see johnny run out of bullets as he shoots and sure enough when we look at the output here it says johnny english prepares to attack and his gun now has no more bullets in it okay so let's see what we were supposed to learn from this so we created this idea of a services a service collection which means we're going to associate objects with a concept so the concept is we are going to first of all think about the concept of an eye weapon and you can see that we copied and pasted several things we had swords grenades and guns and they could be swapped out for whatever i weapon was going to be defined as by one line of code the second thing is we had a hero that was also swapped out so we could have changed out johnny english just as easily with this line and so hero 5 could be flexible it could be johnny english it could be batman it could be anyone we want to define now all of this code here is supposedly independent from the program so instead of putting it in program cs like we have in this example the next example that we're going to code will actually go into a config file in asp.net and so the next example will be more realistic and will show us where you would use some data sources to be defined as dependency injected or not so let's go to the next coding example right away in this activity we had done in a previous tutorial we have a list of products and you can see that i have searched for soup and all of the items that relate to soup show up now what we're going to do our code change is the actual data source so all of these pictures and these products are coming from a sql database in a previous version of the tutorial we created a hard-coded example and all of the changes were we're going to be able to set up right here in the controller area where we have the repository defined so let's do a quick change to switch from a data source to another data source and then we'll do dependency injection so first of all let's take a look at the data sources that are available to us so i have a folder called services and you can see that there is something called an i product data service interface and so the interface is a key point here we have an interface that defines two different types of data so the one that we've been using in recent tutorials is this one called the product dao and as you can see it has all of the same actions as the interface but we talked to the sql database the other is called a hard coded data repository and literally we just defined the objects in the code as strings and so we could swap these things out using dependency injection so now let's go in and make a change manually into our products controller so i'm going to open up products controller cs and we can see here on line 14 and the constructor that we're using the products dao which is the database of the sql database so i'm going to comment out that line which says define repository i'm going to redefine it so the type now is called hard coded data repository and we'll instantiate a new instance of that using the same name now you can see that there's an error down below that says the repositories types don't match anymore so let's replace one with the other and so now we have replaced repository with a different data source so this is the manual process of changing our code in just a moment we'll use dependency injection to do this in a configuration file separate from the code but the result will be the same so when we run this we should see different data so we got the application up and running i'm going to choose the products link and this time we're not supposed to see soup we're supposed to see the hard-coded values and so sure enough the first five values in the hard-coded were computer things such as a mouse pad or a hard drive and then these ridiculous names that came from another fake data source but the data is different now because we have changed the data source now instead of going in to code these manually let's implement the dependency injection using something called the unity framework all right so the next place we're going to look at is in the service or i mean the startup cs file and so in startup cs this is where we can configure dependency injections so i'm looking for the section here that says configure services and we're going to just insert some new lines here and do our dependency associations now the line that we're going to include is going to be this uh services dot add transient and then the brackets now we're going to associate a cloud an interface type with a class type so the i products service or data service is the is the type now we have to import that or use the services folder so we'll do a little bit of a injection there or a code in include and then we're going to tell it which one of the data services that we want to use so in this case the first example is hard coded data repository and so this one line then is where we would change our data service now let's go to the controller again and we're going to comment out the the property called hard coded data service now we're going to make a new property its data type is going to be the interface so i product data service interface we'll still call it repository and we'll have a get and set now the constructor then needs to have some kind of a parameter passing in which type of data service we're using so we'll put in the property of product i product data service and we'll call it data service as the name of the parameter and now repository is going to be assigned to that now this is going to take its cue from the config file that we just used in startup let's see if it actually runs so i got the app up and running let's go ahead and click the products link and hopefully we get some data and sure enough we have the same thing we did before this comes from the hard coded values so we can see that because i remember the first five items were all computer parts such as mouse pads webcams and so on so it appears that the data service has been defined correctly as hard coded now we're going to switch this with one line of code now to switch this i go back to the startup file or startup cs and the line here where it says we're going to associate the i product data service with something we can swap this out so let's take out the hard coded one and the other was called dao wasn't it so it was uh products dao was the item i'm looking for and now the program should change the data source and i never have to come back and actually code anything anymore in the controller so let's run this and see if the switch actually occurs so the app is up and running and let's go ahead and choose products and see what comes out now as i remember products kind of run slowly when it's talking to the database because of so many items but here we go we got the right things so we've got tacos and flowers and an energy bar and it looks to me like we've got food here instead of the other products so in one line of code in the configuration we have done the dependency switch so i'm just going to go back and do one more cleanup i've got these two items that are commented out you could optionally delete those and now we have something else that is more running with dependency just to make things more clear to other programmers that might be maintaining this program i'm going to put a note that says use dependency injection c startup cs to see the data source for repository and really we've got ourselves a very flexible thing now so why would you want to have two different data sources well think about how you would run your program in a development environment sometimes you want to do testing and sometimes you want to have it in production so if you're trying to update or delete records in a production database that's a bad idea in this case we'd probably just want to switch to a test database where it doesn't matter if we wreck the data or not and so with one line in the config we can swap out two different data sources so there's an example of dependency injection in more of a real world situation so just to recap why we were doing this remember that dependency injection is this programming technique to make classes more independent of each other hopefully you can see the independence now classes are more reusable they're more testable less rigid and they are going to pretty much have this one feature where we're using interfaces to pass along types of items in our constructors and so in the case here we could swap out the wheels of a car using an interface rather than a hard-coded value so just remember the one final rule here that when you're writing a definition for a class don't instantiate anything inside of it think of dependency injection as a better design pattern that will be more flexible for you in the long run so thanks for watching this was a long video on dependency injection and appreciate you sticking with me here to the end we're going to move on and do some more things with caching and asp.net in just a moment you
Info
Channel: Programming w/ Professor Sluiter
Views: 2,539
Rating: undefined out of 5
Keywords: dependency injection c#, dependency injection, dependency inversion principle, dependency inversion principle c#
Id: CJRvRdOR7Ls
Channel Id: undefined
Length: 39min 4sec (2344 seconds)
Published: Tue Feb 16 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.