BrandGhost

Your ASP.NET Core Blazor Apps NEED Plugins - Here's Why and How

Microsoft's ASP.NET Core Blazor framework is an incredibly powerful way to build web applications. Do you know what would make your web app even more powerful though? Leveraging plugins to be able to extend functionality and add features with ease. Let's see how we can use Autofac in Blazor to accomplish this! Have you subscribed to my weekly newsletter yet? A 5-minute read every weekend, right to your inbox, so you can start your weekend learning off strong: https://www.devleader.ca/newsletter...
View Transcript
if you're not using plugins already in your web development I think it's time you start using plugins and plug-in architecture can really help make your application extensible flexible and honestly a lot more maintainable so if you like the idea of being able to add more features to your web application without risking breaking the other parts of it plugins are an awesome option for you to consider in this video I'm going to show how we can use plugins with autofack inside of a Blazer web application and by the end of this you should be able to adopt this pattern for your own web applications and before we jump over to visual studio I just wanted to mention that I've had some requests to put some content together maybe making a course around building plugins and designing plug-in architecture so I am going to be starting on that and putting some content together for it I will be making a course and with that said if you want to subscribe to my newsletter that's where I'll be announcing that first so if you want early access to no one that's going to be releasing sign up it's totally free alright enough blabbing let's jump over to visual studio alright so in Visual Studio I've just gone ahead and created a sample Blazer web application and I've started to make some modification to it and I'm going to walk through that to show you how I have Auto facts set up and how we'll get plugins registered so full disclaimer this is totally based off of the sample app that when you walk through to create a new blazer project this is basically what you get out of the box I've just started stripping some things out and adding some additional things the first part that's going to be different is actually leveraging Auto fact here so what I've done is I've added this Auto fact extensions dependency injection nuget package and if you want to understand just the basics of getting this working I'll link a video above and you can go watch that and come right back here but the first thing we're going to want to do once we have that is configure Auto fact to be our service provider and yes Microsoft does have their own dependency injection framework but my preference is using Auto fact I'm most familiar with it and I really like the functionality that it comes with so what I have on screen at this point right here is really the core part that's going to configure Auto fact to be the dependency injection framework for our application but the piece that's inside that I have highlighted right now is what we're going to use to discover and register plugins so just to briefly explain what this is doing it's going to check for files in our directory where we're running from and it's going to look for any dll that has plug-in in the name it's only going to be searching in the top level directory and for what it's worth this part is something that in your own application you might want to configure to be different so maybe you want to look in a specific folder for plugins or different folders you might want to look for plugins with a certain name or something like that this is totally just an example it's not going to be perfect it's not going to be Bulletproof the next part that we do inside here is that we're going to load the assembly from the file and then we can register all of the modules in that assembly to autovac the variable CB is just a container Builder and that's part of Auto fact where we're going to register all of our dependencies to that and then the container Builder will build a container which will be our service container that we can resolve dependencies from again in your own production application you might want to put a little bit more safety around line 17 here that has the assembly loading just in case something goes wrong and you can decide how to handle that gracefully or blow up your app if you need to other than that though there's not a whole lot else that's changed in the top level part so I've removed the part that actually registers some of the example services and stuff that they had in here because we don't need that anymore I think they have like a Weather Service and that kind of thing I've actually replaced that with the plug-in part we're going to look at so that would probably be right after line 23 here if you're using the the default application that gets created so this is what we're replacing it with and you'll notice that I don't have any specific plugins being registered here and that's because I'm going to demonstrate that we can just drop plugins into the bin directory and they'll automatically get taken up when we start our application the next thing that I want to highlight is that if we want to have plugins we probably want to have an API defined for what those plugins can do I didn't get very creative in this example so I just made an i plugin API it just has a single method on it called get data async that returns a string now based on your a particular use case you're going to have all sorts of different things here that you might want to expose for plugins and I figured there was no point in making this part complicated for demonstration purposes I just want to show you how you can create something and then we'll be able to register it and resolve it and then use it you'll also notice that in the solution Explorer I've actually put this interface into a separate project here and I just have it called dot plugin API and the reason I've done this is to demonstrate that when we go create another project so a totally separate plug-in Library that's going to be separate from our base application that instead of having a weird dependency where the plug-in Library depends on our core application the only dependency it really needs is this interface in your particular application you might want to have some type of libraries or infrastructure that plugins can use but we're just keeping it simple here and exposing one single I plug-in API that our plugins have to implement and that way when we go to resolve them we're looking for all of the I plug-in apis that are accessible to us I do have one one single implementation of a plugin called plugin a and there's plug in a library that we'll look at after but what I'm going to walk through is the core app so we can see how we're going to use plugins and that way when I go to show you plug in a library you'll understand how that's going to be leveraged so in the core application I have a plug-in provider so I'm going to go to that class right now so this is super simple and I've left out a lot of pieces here and all that we're going to be able to do is illustrate that leveraging auto fact we're actually able to go resolve all of the plugins and then we just have a method called get plugins to return them so explain what's going on here this is really more about Auto fact usage so what I have is an i enumerable of I plug-in apis and you'll see that it's wrapped in lazy as well so the idea here is that when we go to access the plugin provider for the first time depending on how much work was actually required to go resolve all of the plugins and how heavy of a lift that was so for example if your plugins actually had work that they were doing in their Constructors to initialize or something like that all that I'm trying to do is delay when that work is going to take place this is just a little extra thing here because if you had something like this this would help you have your startup time be reduced a little bit in a situation where plugins could technically take time to initialize in our particular case that's not going to be a concern at all but I just wanted to demonstrate that you could take advantage of something like this you'll see that we're going from I innumerable to I read only list and the reason that I still have lazy wrapping and I enumerable because I enumerable can be lazy loaded it technically on its own is because with auto fact I'm pretty sure it's already resolved and created the instances of the plugins if we were to just do this but with lazy wrapping it we're actually able to delay when those plugins will actually get created so again this is just a little bonus thing if you want to consider that for your own application to help with startup time but beyond that really all that we're doing is returning the value of the plugins for this get plugins method so nothing really fancy here at all but the magic is actually happening because the way we're going to register this plugin provider is that auto fact will be able to automatically insert all of the I plugin API implementations for us so if you're thinking about the benefit of that it's really awesome because we don't have to manually go register plugins anywhere it's just going to feel like it's kind of magically taking up new plugins that are available in the bin directory for us at startup time and just to reiterate one of the reasons that I really like plug-in style architectures is that we're able to extend applications without having to modify the base application so taking steps like what I'm showing you on screen right now are helpful in making sure that we can have this automatically resolved plugins without touching the base application so the next part that's in here that's Auto fact related is actually the auto fact module where we have to register this and it's really simple actually so with an auto fact module we just need to override the load method and all that I'm doing is registering the type plugin provider and making it a single instance from the perspective of the core application we don't have to do any fancy plug-in registration or anything like that we're simply just registering this plug-in provider type and then we're leaving it up to our plugins to actually go register modules for themselves we'll get to that in just a moment but I'm going to show you the Razer view where this information is going to be shown so back to our solution Explorer if I go to fetch data this is actually where the weather example was I've just changed some of the text up here to show that it's going to be for our plugins and I've modified this a little bit so the view that we're going to have is going to say the count of the plugins and the weather example had a table that would print all the weather information out so I just changed that to be a single column that says plug-in output and what we're going to do is for each of the plugins we're just going to call get data async on that plugin I realized after when I was creating this the get data async Maybe wasn't the best usage here because we can't really await things that are async inside of the Razer view so this looks a little bit nasty I apologize I probably could have just made it a property to keep things simple or if I show you the part down here what I probably could have done is actually made it so that it wasn't the list of plugins that we're looking at but instead the output but regardless on initialized async all that we're doing is asking the plugin provider to get the plugins because this part's technically synchronous I just put a task yield in front here so again in an example where this was taking a long time we'd at least have the opportunity with this task yield to allow the schedule to run something else in the meantime so once the plugins are set if we scroll back up you'll see there's a null check here on plugin so it'll say it's loading while plugins are null and then when it's not we'll actually be able to have this information get populated okay so both before I show you the actual plug-in implementation which is going to be very simple I figured let's go run this thing let's see what it looks like and then I can demonstrate after showing you the plugin implementation just how easy it is to make a plug-in work alright so I'm running our sample application here and we can see that we have this nice fun text at the top here I've left the sample counter piece in here I haven't stripped that out but if we go to fetch data that's where we're going to run our new plugin code and we can see the title here but this is where we're actually checking how many plugins we have right so there's zero plugins because we haven't added any and this is where we would see the plug-in output but because we have a for each Loop and there's nothing in there nothing's going to be output below it so it's pretty boring right now but we needed to see this first to be able to prove that when we go to add something this will change all right so let's go check out that plugin a code so in our solution Explorer like I showed earlier I have this plug-in a library I'm going to go to that right now and we'll see two files we'll start with plugin hey so plugin a is super simple it's just a class that's implementing I plugin API which like I said earlier that's the only requirement that a plugin has to implement and all that I'm doing is returning a string here that says data from plugin a the whole point here is that I just wanted something that would illustrate that we have something coming from this particular plugin and not something super generic so the plugin itself is really really simple but the other piece that's going to make this work is the module for auto fact so I'm going to jump over to that now plug in a module and it looks similar to the other one that we looked at earlier so we'll have the container Builder that's passed in to this load method that we have to override I'm going to register the type plugin a I'm going to say as implemented interfaces because it implements the interface for I plugin API and then again it's going to be a single instance so I wanted to pause for one second because if you're thinking about what a plug-in library look like here we had one file that was one class that had to be the plugin itself and then a second class that's the module to actually register that plugin now something to consider in your design is whether or not you want your plugins to actually have to care about autofack in the example that I'm showing you right now it would mean that every time we wanted to go add a plug-in they need to have a dependency on autofac in order to be registered into the container and that might be totally acceptable for your application but otherwise and I'm not showing in this example you could use something like reflection to go iterate through the assemblies iterate through the types of those assemblies and look for everything that is I plugin API at that point you could manually go register all of those things individually and you could build that right into the core application but instead all that I'm showing you here is that if we wanted to keep adding more plugins each one of them would also need to have a module just like this personally for a lot of my projects I already have Auto fact being used in plugins anyway not just to expose the plugin but actually internally used within the plugin so because I already have Auto fact as a dependency for almost everything I do I don't actually have an issue with doing something like this and having a module however there are a lot of opportunities where when I have a lot of plugins of a particular type it gets a little bit annoying to have to remember to manually register each one even if I already have modules like this so a lot of the time I will have a bit of a hybrid approach where I do have some reflection to go register types but I just wanted to mention it because if you're watching this and you're thinking about how you might apply it you may want to consider something like that for your plugins alright so to actually make this work with our core application we don't have to change anything in the core app but all that we have to do is build plug-in a library and then take the dll output of that and put it into the bin directory of our core app so I'm going to go ahead and build this now and then I'm going to take the files copy them into the bin directory and I'll press run again to show you what happens all right we're back in the sample application let's press fetch data and see what we get awesome so the first thing we can see is that there are one plugins yeah I probably could have put the S inside of some braces here to make it less ridiculous when you read it but there are one plugins and if we look at the plugin output we now have an additional line here and we can see that this is the text that came from plugin a and I know in the recording here I've jumped from Visual Studio you didn't see me copy the binaries and I can't prove that I didn't go edit the core application but if you trust me all that I did was I copied the dlls into the bin director tree of the core app and just relaunched it and that is how we can extend a Blazer application with plugins alright so that was just a quick video for today to be able to walk through how we can have Blazer applications with plugins inside of them now I know the plug-in example I use was really simple it just had a single method on it that was returning a string but I wanted to keep it simple like that because it's going to be up to you and your application to understand what kinds of plugins you want to include in the example we looked at I used some techniques that would allow automatic discovery of modules and plug-in dlls but I did call out that each plugin in particular would also have to have an auto fact module to register the plug-in itself you can use reflection to be able to register things from other assemblies so that's totally an option I use it in a lot of my own personal projects but in this example I didn't show that we're just requiring that you have a module for each plugin and then all that we had to do was build the project drop the dlls into the bin directory and the main project actually was able to launch and take up those dlls and show you it right in the UI so I hope that helps illustrate to you why plugins can be super powerful in things like Blazer apps and I hope that you take advantage of it for yourself thanks for watching and we'll see you next time

Frequently Asked Questions

Why should I use plugins in my ASP.NET Core Blazor applications?

Using plugins can make your application more extensible, flexible, and maintainable. They allow you to add features without risking the stability of the existing application.

How do I register plugins in a Blazor application using Autofac?

To register plugins, you need to configure Autofac as your dependency injection framework and set it up to discover and register plugins from your specified directory. You can do this by checking for DLLs that contain 'plugin' in their name.

Do I need to create a module for each plugin I want to use?

Yes, each plugin needs to have its own Autofac module to register itself. This is necessary for the plugin to be recognized and utilized by the main application.

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