.NET Generic Host - WPF MVVM TUTORIAL #9

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
we have the core functionality of our application completed but one thing you might want to consider implementing in really any application and usually from the start is setting up the net core host so that we can manage our application's lifetime we can handle configuration values we can set up dependency injection set up logging there's just so many things you can do with the dotnet host so we are going to set that up for our wpf application so you're probably most familiar with the.net host if you built asp.net web applications because it scaffolds that out automatically but the wpf.net core template does not so we're gonna have to set that up manually and to do that we are first going to install a nuget package and we can probably just search hosting here and we want microsoft.extensions.hosting so we're going to install that and in our app.xama.css so right here in our app constructor we can take the host and import that from microsoft.extensions.hosting and we want to create the default builder and now we can just configure everything we want to we can configure services for dependency injection app configuration so we can load values from some kind of app settings.json such as this connection string which i think we will do i don't think we're going to be going into logging that much i have another video on logging because that is an important part of wpf applications but that is optional it is preferred though so i recommend checking that out but we're not going to cover it in this series but we are going to do is configure our services so this is we're going to set up our services for dependency injection and we do that with a callback function and this parameter is our service collection where we register the services so we do have some services we want to register such as our ireservation provider the ireservation creator and pretty much everything that we set up in this app constructor we want to manage that independency injection so we just resolve everything without having to manually pass everything in so we'll take our services and we are going to add a singleton so we're going to import that from microsoft.extension injection that's what we're doing and i guess the first thing we're going to register is our reservium db context factory so we can just pass in the instantiation that we do want to register so we just copy this constructor actually cut it and paste it into our registration and i guess we don't need this type here anymore and we can remove that down here so registering something as a singleton means that we're only going to have one instance of that type shared throughout our application so every time one of these services requests a reservem db context factory it's going to be the same instance so speaking of those services let's go ahead and register those in dependency injection as well and these can be singletons as well so the i reservation provider we are going to map to a database reservation provider and then our i reservation creator will be a database reservation creator and lastly the reservation conflict validator will be a database reservation conflict validator and we can now remove these down here next up we have the reservation book we can register that as i guess transient in this case so the reason we're doing it as transient is because our hotel is going to request a reservation book and for now we only have one hotel in our application so it wouldn't really matter if we registered the reservation book as singleton or transient but if we had multiple hotels in our application somehow we wouldn't want every hotel to have the same reservation book we want them to have different ones so by registering this as transient it means that every single time we resolve a reservation book in this case it's going to be a different instance which i believe we want in this case and for this reservation book since we registered all of its dependencies already we should be good to resolve that eventually next we have our hotel and this can actually be registered as a singleton because for our application we only have one hotel so just register that and for the hotel we actually have to register this with a factory function because we're gonna have to manually pass in the string name because we don't register a string in dependency injection i don't even know if that's possible i've never really tried but it wouldn't really make sense so we're gonna use a factory function here which takes in our services as a parameter and inside here we can just instantiate our hotel pass in the name we want so singleton sean suites and then to get our reservation book we're not just going to instantiate one here we don't want to do that instead we can use our services parameter here so this is a service provider and we can use that to resolve a reservation book so that'll give us the reservation book from dependency injection that we register and i guess we don't need this type either and then lastly we have our stores so these are going to be registered as singleton because stores as we recall they manage our application state so we want that to be centralized in a single instance so we're going to register the hotel store and then the navigation store and that should be everything we need for our services so let me move this onto a new line clean it up a little bit but now lastly we are going to build our host because right now we're just configuring a host builder but we got to build it so let's do that and that gives us back our host so the host is going to go into a field in our app so let's generate that field and we can remove all of these other fields we have because those are going to be managed in dependency injection now so now we have our host in the field and now we can use it in our startup so first we are going to start the host and now we don't have a residriumdb context factory here but we can just resolve that from dependency injection so get the db context factory using our host services and we are going to get a required service so this is resolving it and we're getting our db contacts factory and now we can use that down here next we want our navigation store so we can do this initial navigation so we're going to use our host and resolve the navigation store and now we can just use that throughout here and lastly we have our main window which also takes a navigation store but we could just go ahead and register the main window in dependency injection so that we can just resolve it right here so let me just cut this out and what we would want to do is take our host services and resolve some kind of main window but we're going to register that so let's go ahead and do that up here so i suppose first we could register our main viewmodel we would want this to be a singleton because we only have one main view model in our application of course that could somehow change but we are going to keep that as a singleton for now and then our main window is also going to be a singleton and we're going to register this with a factory function that's going to give us back our main window and we have to register it like this so that we can manually set our data context here which is going to be the main view model that we resolve from our services and let's clean this up and that should all work the last issue we have is all of these dependencies that we use down here so what we're actually going to do is split all of this up and register all this independency injection so i actually want to register this navigation service that takes us to the reservation listing view model so let's go ahead and do that navigation services this can just be singletons so i add a singleton for our navigation service and this is actually not going to work and that is because we have multiple different navigation services and these are the same type so we can't register the same type twice that doesn't make any sense so what we can do instead and it's actually something that i do in my navigation tutorial but i didn't do here is we can make our navigation service generic and then enforce tv model to inherit from viewmodel base and then just use tv model throughout this class which is still going to be a viewmodel base but what this allows us to do is register a navigation service for a specific viewmodel so we can register this for the reservation listing view model and then now we can register another one for the make reservation view model and we're gonna have to account for this generic type all throughout our application now so navigate commands is gonna have to be generic now for a tv model and we need that same constraint so tv model needs to be a view model base but now we can just use that all throughout this class and then we just have to update our view models as well so this is a navigation series for the reservation listing view model and update our navigate command for that type we're also gonna have to update the make reservation command because that takes a navigation service this is gonna be one for the reservation listing v model that's where it's gonna navigate us to and then lastly the reservation listing v model needs a navigation service this one will take us to the make reservation v model and then just update that in the command as well and we also have to update our load view model function for the make reservation view model but now we were able to register both of our navigation services so that's good the only issue is that these navigation services take a funk for a tv model which we don't have registered in dependency injection so that means we're not going to be able to resolve any of our navigation services but that's no big deal we can register these funks so i'll keep that with my other view models so we need to register a funk this can just be a singleton so we need a funk to create a make reservation viewmodel and we'll register this with a callback function so now that's where it gets weird we have to register a function so this function takes no parameters and is going to give us back a make reservation view model so there's multiple ways we could do this how about we eventually register our make reservation v model in dependency injection so we just resolve it here and there we go we've registered a funk that gives us back a make reservation view model but now we actually have to register that view model so we're going to register this as transient because like we mentioned view models are going to be created and destroyed throughout our application so that we can dispose them so we're going to register a make reservation view model and we should be able to just resolve this because if we look at this constructor we have our hotel store registered and we have a navigation service for reservation listing v model registered so that should all be good now we just have to do the same thing kind of for the reservation listing view model so let's just copy these except this time we're registering a reservation listing view model and looking at the constructor for that we have everything registered that that view model needs so now we just need to register the func for that and we just resolve that v model from dependency injection and now we do not need these methods down here everything is managed in dependency injection except we were using one of those methods but what is this doing well this is just navigating us to the reservation listing view model so instead what we can do is resolve our navigation service for the reservation listing view model here and now we can just call navigate on that and that'll do our initial navigation for us so we got everything registered now we're starting our host resolving everything we need one thing i wouldn't do is whenever we exit the application we should dispose of our host but now i'm feeling pretty good we should have our application functioning so let's see this in action and here we go we hit our view reservations page and i can still navigate around so that's all good i don't know where my reservations are maybe i deleted my database by accident but let's create a reservation there we go all good and still not displayed i hope i didn't break anything in a previous video let's go ahead and debug this oh you know what i know what it is so we're not even hitting any of these break points and that is because the way we registered our reservation listing viewmodel so we actually don't want to register it like this because this just calls the constructor and we don't want to call the constructor we want to call our loadviewmodel so that does the loading for us so to do that we are going to have to expand this into a factory function so we can manually call loadv model and then we're going to pass in all these parameters manually as well so let me just move all this to its own function so we'll call this create reservation listing viewmodel and that's going to need our services passed to it so that we can resolve everything we need so generate that and in here we can just call loadviewmodel and then resolve everything we need from dependency injection so we need our hotel store and we need a navigation service for a make reservation view model all right so that was an easy fix better than expected i was getting worried there but now there we go we're hitting the loading screen and there's all of our reservations and here's the one that we just created so everything is still working fine now what else can we do with the host well we can configure logging but like i mentioned not gonna get into that the other thing we can do is configure app configuration so this is how we load configuration values such as from an appsettings.json which is what i want to demonstrate so we're going to move our connection string into the app settings.json and maybe our hotel name that'd be cool to put into the app settings as well but let's demonstrate how we do that so first in our project we're going to add an appsettings.json i believe it's a file type all right i don't see it in any of these so what we're going to do is just select json file and we'll call this appsettings.json and we can have a connection strings object here so expand that into an object and we'll just call our connection string default and then we'll just paste in our connection string so let's grab that from the app.xml.cs pretty simple let's just cut that out plop it in our app settings.json and we can remove that here now so now we just need to get our connection string here from our appsettings.json and then pass that in so how are we going to load that connection string well first what we can do is change this callback so we get our host builder context so what this is going to do is take two parameters the host context and our services again which we use to register so if we look at these parameters we still have our service collection but we also have this host builder context so we can use this host builder context and we can get the configuration so this configuration is going to contain our app settings.json values so we can get a connection string so import that method from microsoft.extensions.configuration and we named our connection string default and that actually gives us back our connection string so we can use that value and then just pass it into our db context factory but i did say we are going to have to configure app configuration so that we load our app settings.json so something like this open this up with a callback and we get our configuration builder and we would want to add a json file and point to our app settings.json but we actually don't have to do this because create default builder this default builder does this automatically for us so we don't have to configure it here we get all that for free that's wonderful but let's put a breakpoint here and make sure we get our connection string because we might have to change some properties on the app settings.json not entirely sure but let's check and yeah our connection string is null so i think what we need to do is come over to our app settings.json and configure the properties for that and we want to copy this to the output directory i guess only if newer that should be good and there we go now we have our connection stream so i believe the issue was that our app settings.json wasn't being copied to our bin where the application is being executed from so the application just couldn't find the file but now i can because we copied it to the bin on build and now there we go our connection string works and we load all of our data so that is the main power of the host the other thing you might want to consider is logging but i think i've said this like three times already i covered that in another video i suppose the other thing i'll mention if you did want to clean up your app.xaml.cs what you could do is in our project we could create a new folder for host builders i guess you could name this whatever you wanted and we'll create a new class in this folder and i guess for this example we'll call this the add view models host builder extensions and inside here we'll just have a static method that'll give us back our host builder but we'll call this add viewmodels and this is an extension method so we're going to prefix our host builder with this so we can call it fluently and this class actually needs to be static because we have an extension method inside of it but now in our app.example.cs we can move over everything related to view models so just cut it out of here and we can use our host builder and configure services get our services call back in here and paste in all of our view model service registrations so we're going to import all this junk we need our create reservation listing view model function in here so we created that earlier so that we could do our load view model manually so let's just cut that out of the app.cs paste it in here this will have to be static and then finally just return the host builder from this method now that we've configured it so now we have our view model stuff separated which cleans up our app.xaml.cs and now all we have to do is we can call our extension method add viewmodels so import that we can move our main view model in there as well so our app.xama.cs is a little bit more concise you could go through and do this for all of your other services you could have some kind of ad stores maybe an ad services and add models and then you would just go through and call all those extension methods so like i said the benefit of that is that the app.xml.cs is more split up but one drawback is that now all of our service registrations aren't consolidated in one single place so it might be a little bit more difficult to find things when you need to change them although it is more organized like if you had to change something with view models you would know to go to the add view models host builder extensions but i don't know i guess there really is no right or wrong way if there is i really couldn't tell you because i really don't know even though i've tried both ways i really can't tell which one i prefer better but i just wanted to demonstrate it real quick just to throw it out there if it's something you're interested in doing so we got our host builder set up we registered our services and we even set up an app settings.json for our connection string so hopefully you find this helpful for your own applications so you can manage your application's lifetime register and configure all of your services instead of logging if you're interested in that and then set up configuration values in app settings.json as for myself this is something that i usually like to set up in my own applications but anyways if you have any questions criticisms or concerns be sure to leave them below in the comments section if you enjoyed the video or are enjoying the channel consider becoming a member other than that leave a like or subscribe for more thank you oh one last thing we forgot to move our hotel name into the app settings.json let's cut that out plop that in here the hotel name set that value and then get that down here so the hotel name will come from our host context configuration and we are going to get the value of our hotel name key which is a string and then we just pass that in and there we go single touch on suites let's go
Info
Channel: SingletonSean
Views: 1,844
Rating: undefined out of 5
Keywords: wpf, programming, visual, studio, xaml, custom, control, generic, system, line, display, timer, template, binding, c#, how, to, series, tutorial, easy, time, maintain, package, design, part, event, code, framework, register, static, state, default, view, style, wrap, panel, stack, scroll, viewer, first, width, action, void, model, layout, user, box, mvvm, data, error, icon, class, relay, clean, simple, sub, log, file, host, grid, scope, align, margin, deploy, github, actions, download, essential, validation, rule, logic, storyboard, story, navigation, store, builder
Id: dgJ1nS2CLpQ
Channel Id: undefined
Length: 18min 13sec (1093 seconds)
Published: Sat Nov 20 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.