BrandGhost

*SO* Close To Plugins In C# - Autofac in ASP NET Core

This is the second video in my series explaining how to get the most out of Autofac in ASP.NET Core. The first video examined the suggested way to set things up -- but this video goes against the grain with setting up our dependency injection container! In this video, I'll explore the trade-offs of using an Autofac ContainerBuilder in contrast to the recommended way of setting up an ASP NET Core app. We're getting MUCH closer to having a workable plugin setup!
View Transcript
in asp.net core there are many ways that we can set up dependency injection personally one of my favorite ways is to use a Nate package that's called autofac hi my name is Nick centino and I'm a principal software engineering manager at Microsoft I've made other videos about working with autofac and written articles about this as well especially in asp.net core in one of my last videos which I'll link up here I was walking through the recommended way to set up autofac in asp.net core going through that process there are a handful of things that work really well and a couple of things that don't work so well so I wanted to continue to explore different ways that we can set up autofac and in this particular video I'm going to walk through just setting up a container Builder and not setting things up through the I service collection a quick reminder to subscribe to the channel if you like this kind of content and check out that pin comment for my courses on dome train with that said let's jump over to visual studio and look at autofac so I did mention that we're not going to be using the I service collection to wire up our dependencies and instead we're just going to start with the container Builder that autofac has what I really like about this approach if we look at the all the code that's above line 20 we can see basically this cu the rest is just comments and some using statements this essentially just becomes your program.cs it's extremely lightweight on line 13 this might change a little bit depending on where you want to register modules from we can do assembly scanning and stuff like that so you don't have to register them all individually so this line could change maybe into two or three more lines but other than that it's really really lightweight and I love this kind of thing just to keep it super simple it essentially means that we should never have to come back to program.cs as we scale out our application so one code file that basically never has to change is a thumbs up for Mee now with this approach we end up having all of our registrations inside of this my module class and like I said this could look different in your application but for this example I'm going to show you it all in this one module and modules are things in autofac where you can set up all of your registrations if you're not familiar with it and I am going to be walking through what should be very similar to the sample weather application when you go make an asp.net cor app this isn't something I've gone and created from scratch I've just modified it so it should look very similar especially if you want to on your own go through this code which I will link in the description below and you can set up a new project with the weather application and compare them side by side so this internal record is just from that sample application but this my module class is where we start to have our own registrations but I will do a quick scroll through this because we'll start to see these familiar dependencies if you've gone and watched that previous video but you can see right here this is where we start to register our well our single minimal API for weather forecast and this is where I have done some modifications to that API to prove what we can and cannot do so the comparison that I was trying to do in the previous video was essentially that I want to pass in things on the minimal API and see if we can get dependency resolution to be able to find these services from our dependency container and if we go look at these dependencies I have them defined below here you can see that they are going to take in other dependencies so I want to see if we can access the web application Builder sort of Auto magically through the container resolution the dependency B here takes in the weather application so this is the instance that gets built from this one here on line 129 an i configuration is accessible from web application Builder but these three dependencies right these ones here like on the parameters that are passing on the constructors these are ones when I go to build plug-in Frameworks I like having access to these things so for me this is sort of a minimum bar that I want to be able to set for myself between those three things and being able to set up minimal apis and have that passed in I think that that's a bar that I want to set for moving forward if I scroll back up to the other resolutions because I did skim over these these are just the three dependencies that we just looked at and then what we want to be able to do is register the Builder itself on the container so we should be able to automatically resolve that the I configuration that comes off of that web application Builder and I did a similar thing in the previous video where I did have this web application Builder being resolved off the context in that video I did not have to have this resolution because I had access to the web application Builder already in this setup we don't have access to it unless we resolve it off of the container but between these two things we should be registering two of the dependencies that we need for these three dependencies but we're still missing one of them we are still missing registering the web application itself but if we scroll through and look at this other registration here we don't end up needing to add the web application onto the container itself right so we don't need to do that in order to register the route but if we go run this we will see that there is one problem because we set it up this way where we are resolving the builder then building the app and then never putting the app onto the container Builder itself what ends up happening is that we should not be able to get this dependency resolved dependency B and that's because it truly does need the web application on the container so let me go run this and we'll see that this minimal API is not going to work but wait a minute it's not complaining about dependency B in in fact in the previous video we saw that this was the first limitation where dependency B wasn't working because of the web application but why is dependency a not working in this case the very first dependency on the minimal API doesn't work for us well let's go back to the code and have a look here one of the things that's challenging here is that we set all of this stuff up with autofac but what we didn't do explicitly was set up the application itself to have dependency and injection with autofac that's what the previous video did we used the autofac service provider to be able to configure the application for that in this video we did no such thing so all of the dependency resolution that's happened up until this point has not had to use that and in fact this application is still going to be using the default I service collection that means that anything we want to go resolve automatically using the application is not going to be using autofac whatsoever now if I go span this comment I've kind of made note of it here so if you want to pause the video you can read what I've said but I'll just summarize it very briefly if we want to be able to access these dependencies what we are unable to do is pass them in as the minimal API parameters we can go ahead and resolve them ahead of time right in this bit of code here right so I could go uncomment this we could go have that run but we have to go do that ahead of time have access to them and then get rid of them off of these parameters here so do doing this approach we cannot resolve dependencies automatically on the minimal API itself that is one drawback but let's look at a way that we can work around this right so I mentioned that we could go ahead and we could resolve the parameters ahead of time so that's one way but something else we can do if I scroll down I have some code commented what we could do is go move that route registration essentially into a dedicated class and I guess this is really not the registration this is strictly just defining the method right so we have a class that can take in the dependencies right CU we can go put this on our dependency container and autofac will automatically go inject these dependency so that will work great dependency B still won't work for us in this setup and that's because dependency B still relies on the web application that is going to be a limitation with this approach as well the whole way through we are unable to put the web application onto the container itself therefore we can never go resolve it I just wanted to leave it comment out and reh highlight that in this approach and the approach in the previous video we are unable to get web application onto the container these other two dependencies though we certainly can get to work then what we do is we expose this forecast method which is really just the body of that minimal API and then we go back up and I can show you how we go register this so the first part of the registration is that we're going to resolve the actual class that we wanted to create right the one we just looked at and then I can use app map get make a new route or replace the one obviously if we don't want to use the normal weather forecast that's broken and then we just pass in the method you can see that on the minimal API itself we don't have to go resolve any dependencies off of the applications container we have them on our own coming from this context this should go work totally fine but the last piece that's missing for that is that we have to go register the weather forecast routes class because we need to do that in order to resolve it up here so these pieces together if I go run this the first route is going to fail but if we go to two it should pass so there's the first route failing this is totally expected because we didn't change anything for the first route but if we go to the second one you can see very clearly that this one succeeds if we make a little adjustment and we move away from having data passed in on the minimal apis that needs to be resolved from the container of the application itself we can go clean this up and potentially just go move all of our routes our minimal a I Define those in dedicated classes this might even be easier to test so maybe not such a big drawback but it does mean that your minimal API definition kind of changes from this nice syntax that you would otherwise have and Define them right in line now one of the drawbacks of this approach is still that because we don't have the web application on the container itself right we're Limited in terms of what we can do before we're trying to think about building plugins if I'm building applications and I want to build plugins that can go register their routes onto the application I can't really do too much because those plugins can't see this application but now that we've seen two different approaches to setting up these dependencies there is a little bit of a pattern that's creeping up and maybe we can just flip things on their head this is covered more in the blog article that I mentioned I Linked In the description and I'll have it in the comments as well but let's go have a look at what we can do because what we're seeing here right is that we're able to go pull in dependency so we can go resolve anything that's registered that we want and then from there this part is now responsible for adding in the route usually what I would like to do is push this kind of behavior into the plugins themselves they can say I want to go register this particular route here is how I want to go register it but we can make a little variation of this so let me comment out this part that does this route registration but I want to like I said flip this on its head what if instead of just pulling in this single class CL we ended up pulling in all of the classes that met a certain implementation and then instead of saying let me go explicitly in this registration go set up all of our routes I just ask those individual implementations hey here's the application I have access to it now you can too so I'm not passing it in via the Constructor and autofac with dependency injection instead I'm just going to pass it as a parameter let's go see how this can work what I'm doing here is I'm introducing an interface that's called I register routes and you'll see that it just takes in the web application itself if we go a little bit lower we'll see that this is a dedicated class that all it's going to do is wire up the routes that we need so it will be able to go resolve the dependency that we already created and registered and then it has a register routes method from the interface and it has that one line that we were talking about doing it's a dedicated class that can do the registration if you think about a plugin approach what we could do is as long as the plugins implemented this interface they could have their own registar that essentially allow us to wire things up that means that these don't have to take in the web application on the Constructor you'll see it's not here but it can take it in on the method call one more thing that we'll have to do is of course register that dependency right so if you were thinking about a plug-in system these are two things that in the module for the plugin you would be able to have essentially get registered and taken care of in the module itself so these would be pulled out into some other project some other assembly to go register things then what we need to do is in fact go perform the registration so instead of the on liner that we have on line 100 we end up having these four lines here in the for each Loop and it just calls on the regist the register routes method let's go run this and see if it works so this is the normal forecast route we didn't change this one still broken as expected but when I go to two we can see that now this is using that other more Dynamic approach for registration this is getting really cool because we're getting much closer to having a plug-in system we've looked at two different approaches so far the first one being the recommended approach if you're setting up autofac with asp.net core we can access the web application in the second approach I did we just started with the container Builder and we're not using the recommended approach for setting up dependency inject ction on the application itself however we do get some benefits and some tradeoffs when we're doing this in either case both of these are limited by the fact we cannot access the web application within the autofac dependency container and that's okay because we just saw that we can maybe flip things on their head to reorder how the registration should work for routes and I am hyperfocused on routes in this case because if we are building asp.net core apps and we want to work towards plugins Reg in routes is a pretty big deal but what if there was yet another way that we could go explore what if we could get the web application itself onto the dependency container what if we could use the recommended approach and still make that happen and get us one step closer to plugins maybe without even having to do what we just saw where we pass the web application in on the method call instead of the Constructor well if you're interested in seeing that and working closer towards plugins you can check out this video next when it's ready thanks and I'll see you next time

Frequently Asked Questions

What is Autofac and why should I use it in ASP.NET Core?

Autofac is a popular dependency injection container that simplifies the management of dependencies in ASP.NET Core applications. I personally find it lightweight and flexible, allowing me to set up my dependencies without cluttering my main program file. It helps keep my application organized as it scales.

What are the limitations of using Autofac without the IServiceCollection?

One limitation I encountered is that when I set up Autofac without using the IServiceCollection, I couldn't resolve certain dependencies automatically in my minimal APIs. Specifically, I couldn't access the web application itself through the Autofac container, which restricted my ability to build a plugin system effectively.

How can I register routes dynamically in my application using Autofac?

To register routes dynamically, I introduced an interface called IRegisterRoutes that takes the web application as a parameter. This allows individual classes to register their routes without needing to pass the web application through the constructor. This approach gets us closer to a plugin system where plugins can register their own routes.

These FAQs were generated by AI from the video transcript.
An error has occurred. This application may no longer respond until reloaded. Reload