BrandGhost

THIS Might Make Me Drop Autofac - Assembly Scanning With Scrutor

One of Autofac's superpowers is the ability to load modules from assemblies. And if that doesn't get you totally excited, let me explain why this is so powerful when we mix it with assembly scanning! If we have assembly scanning in our core application, we have the ability to load dependency registrations from outside of our core application. And if we have this kind of capability, we can do some very powerful things when it comes to dependency injection. But IServiceCollection is making a strong stand against Autofac with this one new cool kid on the block: Scrutor. Let's see how Scrutor can work alongside IServiceCollection in contrast with how Autofac behaves!
View Transcript
it's no secret that I love using autofac for dependency injection in C because historically it's done this one thing a lot better than I've seen I service collection do for my applications hi my name is Nick centino and I'm a principal software engineering manager at Microsoft historically using autofac means that I can do assembly scanning that means that when I want to build plug-in style architectures I can dynamically load everything I need to from the bin directory without having to worry about changing my core application now historically I service ction does not afford US this ability to do assembly scanning but in this video we're going to look at a n get package called screw door that's going to help us get this capability I'm going to walk us through the differences between autofac and how screw door can help us in this particular situation so if you find this kind of content interesting remember to subscribe to the channel and check out that pin comment for my courses on dome train with that said let's go to visual studio look at autofac look at screw door and see how these things compare all right to start things off on my screen I have an example program that's currently a little bit of a mess but I'm going to walk through what's currently there and where I'd like to head to and that's going to show us how screw door and autofac compare when it comes to doing assembly scanning the way that we're going to start this thing off is by basically doing our own assembly scanning here in terms of finding the assemblies that we're interested in I did want to call out that this is a bit of a naive approach but what this code does is it's going to look in the running directory for all of the dll files it's just blindly going to try and load those assemblies up and then we're going to put that into an array there are some concerns here like you don't want to try and load unmanaged dlls you want to make sure you trust the dlls you're working with there's a whole lot of consideration that you probably want to have in production but this is just for demo purposes now what we're going to do from there is go through the autofac example so in autofac the way we set up our dependency container is by using this container Builder and then we have this ability to call register assembly modules and that means that all of the modules which I'll show you in just a moment from any assembly that we were scanning in we'll go register those modules and that means when we look at the modules we can see all of the different registrations per module and those automatically get pulled in this is kind of like a oneliner that gets all sorts of registrations from the places that we're interested in from there we ask to go build the container you can optionally make a lifetime scope like I've done here and then we can go resolve the service that we're interested in so in this case we're going to be looking at a service it's very basic it's just called I my service and it's going to have a concrete implementation just called my service and from there we can go pass in some string that we want to go get output to the console if I go run this example application it's very very simple and you'll see from autofac example printed out to the console because it is a very simple app so there we go there's the output of running this one right so that output really just comes here from line 29 now what's really cool about this and I will be able to show you this in just a moment as we get through this video is that I can move the module that we have in this code that does the registration completely outside of the application and this will all still function accordingly so to show you what I mean by that if we go look at the module which is going to be down here you can see I have this module defined from line 64 through 73 we can see that it's an autofac module the way that you operate these is by overwriting the load method and then you use the Builder to go do the registration that you're interested in in this case I'm just registering the type called my service as the interface that it implements and then saying that it's going to be a single instance that means when other people try to resolve it they get the same instance coming back we are able to go now move this out to a whole new project and as long as that dll that gets built from that project gets put into the folder where we're running from nothing will change and in my opinion that's a pretty powerful thing I'll touch on this more as we get towards the end of this video but I want to now compare how this works with I service collection and it's going to highlight one of the downfalls or at least one of the shortcomings of I service collection in its current state and how screw door will help us and this is just a brief Interruption to remind you that I do have courses available on dome train focused on C so whether you're interested in getting started in C looking for a little bit more of an intermediate course focus on object-oriented programming and some async programming or are you just looking to update your refactoring skills and see some examples that we can walk through together you can go ahead and check them out by visiting the links in the description and the comment below thanks and back to the video the way that we typically see this with I service collection it's very similar right we have a service collection that will create kind of like the autofac container Builder but one big difference is that we end up having these extension methods that we go right so this add my services method is an extension method I've just jumped down to the definition let's go make this a little bit easier to see vertically from there we're going to add the scoped my service we don't need to use that we can do add Singleton if you want whatever you want for your registrations right we go do that right in here but we're using extension methods instead of the autofac module approach so if we go back up and look at this code that's getting run on the service collection example we go call this extension method that will do the registration for us we then ask to have the build service provider method called and get the service provider out of that then from there we can go resolve dependencies so if you were to compare the two methods that you see on screen right now they're very very similar but like I said one of the fundamental differences is that this one is going to be asking all assemblies that are passed into it hey all assemblies go do all of the registrations from your modules what's different about the service collection one is that if we have more modules we want to go work with that means you need to go add more extension methods the more things that you want to have loaded in from what would seem like modules you need have extra calls like this obviously they wouldn't be the uh exact same method name you might have you know different names for all these things probably a lot better than just giving them numbers but the point is that this code exists in your core application if you want to extend your core application you now have to go touch the code inside of your core application to go add more extension methods to go add more code to existing extension methods but the point is you are touching your core application this might not be a big deal at all for you you might say yeah I'm touching my core application because I'm touching it all the time to add features one of my design philosophies is that I try as much as possible to have a very lightweight core application and push things out into different features or different plugins or you might call them something like a vertical slice just a personal opinion about how I like to develop software and that means that I try as much as possible to have a lightweight entry point to my whole application that means that I don't want to be adding more extension method calls more extension methods in general to go register things so now that you have that framing one of the challenges that we have here like I said with the service collection is that by default it does not have assembly scanning but that's where screw door comes into play so if I go check out the project file here you can see that I've added screw door as dependency by the way I have no idea if I'm saying screw door right I don't know if it's screwier I don't know if it's screw Tor I'm kind of trying to go in the middle if you happen to know the right way to say it try to sound it out in the comment comments for me and I will do a better next time but when I live streamed about this I think it was one of the most awkward things I was trying to pronounce so Props to the creator of this for making my life difficult also props to the Creator because this is super cool because it gives us this autofac scanning ability that we could see in the example right up here so how this works is that instead of doing this having the extension methods we can call this scan method now co-pilot has written a a bunch of code already and I wasn't planning for that but basically if I go press tab we can kind of take advantage of something like this it's not exactly what we want but I will try to massage this so it's the code that we need if we have a quick readr from what co-pilot put on the screen it's saying scan from calling assembly that's not exactly what we want because I want to give it a list of assemblies and I think co-pilot probably didn't know that I have that list right so if I were to go pass in the assembly array just like this we should be able to go ask co-pilot to recreate this code so I'll do that in just a moment but you can see that we can then add classes this one is specifically saying just go look for the things that say I my service maybe that's something you want in my case a lot of the time how I write code I want to pull in all of the types that are defined in those assemblies and then we have as implemented interfaces which is very much like what we saw in the autofac module so if I scroll back down literally as implemented interfaces is highlighted right here just like we have in autofac and then we have Singleton lifetime we could change this up a little bit because depending on how you like to write code you can do as self with interfaces if you don't have interfaces slapped onto every single class that you have and there's not a good reason that you should most of the time I do and I do that because of how I like to unit test personal opinion you don't need to go have the interfaces probably as self will work for most of what you have or if you're like me with interfaces will work for most of what you have and of course there's this hybrid that gives you a little bit of both worlds what I'm going to change up here is that we don't want this particular code we want to pull in everything so I'm going to go get rid of this and see if co-pilot will do a better job because I love testing co-pilot especially live when I'm recording this stuff there we go much better um but we don't want add classes still I think we can just do add classes what this will do instead is we will go get all of the assemblies that are passed in we will go add the classes so every type will pull in I want to do as self with interfaces and with Singleton lifetime scope this is nice it's going to give us the functionality we want and we can probably trim this up a little bit this is just a stylistic thing so there we go kind of get this um link looking syntax right overall this should now give us the ability to go scan assemblies just like we had with autofac that means up top here if I go put in this service collection call we will need that and I think for the most part we'll have this working so what I want to do is show you that if we go start refactoring code to go make plugins we won't have to touch any code at all inside of these example methods so I want you to think about autofac example and service collection example as your core applications for this particular situation that means if we want to change or extend functionality I don't want have to touch either of these that's one of the takeaways here that's one of the goals when I'm designing software that I like to have if I go run this we should hopefully see that both of these examples just work and they do so we can see that nothing too exciting but we have the autofac example running and the service collection example running if you didn't believe me that we're not using this anymore let's go ahead and delete it right I'll go run it again I just want to show you that the screw door part is truly working there's no more extension method call and the autoa stuff was still working from here what we want to be able to do is go make a plugin that's part of the goal of this so I want to show you that we can pull out the module and then we can go have the other code running and I'm going to show you two different ways that this would work depending on if you're using autofac or if you're using screw door this is also going to be the thing that may start to push me more in the direction of using I service collection and screw door but I need to get over over that muscle memory of using autofac so the first plugin we're going to make is the autofac specific one um so let's go ahead and add a new project okay so what I've done so far is I've made a new project that we're going to have as our plug-in I've moved the module code from the core application out into this plugin because this is where this would need to live if we were building a plug-in based application and you can see that I'm going to register my service as the implemented interfaces and also make get a single in so same thing I just moved it out and we're going to go look at my service and I'm going to call out one problem that I didn't address before making this project very simple to solve but my service is the same code literally just moved it over here we would have this in our plugin so this is where the implementation would exist but the problem that I didn't address before doing this is that this plug-in and the core application need some common thing that they can refer to and that way when we want to go resolve things out of the plugin and when we want to go Implement them in the plugin we can still refer to the same interface or type that we want to be able to resolve so what I'm going to do is add yet another new project this one is going to be able to be the call it like the SDK and what I'm going to do with the SDK is take the I my service part I'm going to pull that into the SDK again I'm showing you this as a very quick example you would probably want to put a little bit more thought into to the apis your dependencies and how you're structuring that with plugins but this is just to make this stuff compile so you can see these things in comparison I my service is now in the SDK and that means that our plugins should be able to work with the SDK so we'll add that reference that means if we go over to here we can now get that to compile so if I right click I can go build that plug-in excellent this is going to be the autofac one that we're interested in but I still want to go do the same thing with screw door so let's go do another plugin and for this other plugin we're going to do the same thing where we need to reference the SDK because our plug-in will need to know about that interface so we'll go ahead and add that this is going to be the same plugin so I'm just going to copy and paste that code over to here the point that I want to also call out is that you wouldn't be doing this in general having two identical plugins or only doing this because I'm sort of comparing these two different ways to do plugins in the same application so please don't be confused by that you wouldn't be literally copying and pasting these two things and having two of what should be the same plugin it's just for showing you this example the cool thing is that with screw door this is all we have to do I don't need a module if we go look at this screw door plugin you can see that it depends on the SDK but no other Nate packages autofac was similar but it needs this nougat package so this is one of the things I will Circle back on as pros and cons but the my service class is the only thing we need to have in this screw door plugin now let's go back and make sure that our core application is cleaned up because there's probably a couple of things that I broke by doing that and that will be this I my service I need to make sure that I have the SDK added so we'll add that we will add the using statement at the top and now both of these work but there is one more trick if I go run this now there is no dll in the bin directory that will get loaded in and have anything that has IM my service so if we go run this it will crash but I want to show you this first so that you can see it working after it's almost like tdd kind of you can see that it didn't work right it's unable to find IM my service right it says nothing has been registered for that that's okay so we'll have the autofac one go first so I'm going to comment out the service collection one right if I go take that dll from the bin directory copy it in we should see that this works what I'm going to do now is add those DLS so let's go do that so we get this stuff added in here great now if I go run this again I didn't change any of this code I did not touch our core app application I've just added the plugin binaries if I go run this code we should see that we get from autofac right so this is how you would go make an autofac plugin with assembly scanning and let's close that off now let's go make sure we can do the same thing with service collection so we do need to go copy those DLS in again and we'll go run it I've gone ahead and dro the dlls in again this code for the service collection has not been touched this is the exact same as we saw before but we should get the output that we want right so screw door was able to go do the assembly scanning find the type that we're interested in and go get that IMI service to run it to summarize what we've seen here it's two different Frameworks right autofac on its own which leverages assembly scanning and has this concept of modules then we saw I service collection which does not have assembly scanning built in but screw Tor does enable that for us so if you use this Nate package alongside I service collection you can get assembly scanning when we look at the code for both of these they're very very similar with respect to how they operate if we get into the pros and the cons here I would say that screw door sort of gets you this Global way that you want to go do your registrations so for example I'm telling the application that I want to register everything in this particular way that means there's no granular registration I'm just saying grab it all get all all the classes register every single class as itself and an interface and they're all going to be Singletons you might not want that you might not want that because you may want to do some things just as classes some things just as interfaces some things you might not want to have as Singleton if you needed that kind of Separation you'd have to go either break apart your assembly scanning and have your core application know about how you want that to work which in my opinion kind of defeats some of the things that we were looking at but that's how you would need to approach it with screw door if you needed that capability however if we think about autofac and what we're getting with autofac we are making a different trade and that is that every plug-in that needs to work with autofac also needs to depend on autofac that can be kind of messy because you may say like hey look I don't want to enforce that everyone who makes a plugin for my application maybe you have third party plugins that you're trying to have supported and if everyone has to use autofac you might not like that having that as a dependency is one thing it also meant that we had to go make a module and in my opinion this is nice and also not nice right it's nice because you can have explicit registrations you're saying for every type that you're interested in making let me Define how I'd like it to be used that can be good because you get the granularity but also kind of crappy because you have to go manually register everything it also means that you have to have this whole other class whereas with screw door we didn't have that this was the only thing that we needed between these two things we are looking at pros and cons I would say for almost everything that I'm building truly this pattern here with screw door actually fits a lot better but I'd love to hear from you in the comments what your experience is with either of these approaches if you find that the screw doorway just gives you everything you need out of the box if you find autofac is something you've leaned on like I have in the past or if you're doing something completely different I would love to hear about it if you thought this was interesting and you want to see how you can use dependency injection to go build modular asp.net core applications you can check out this video next thanks and I'll see you next time

Frequently Asked Questions

What is the main advantage of using Autofac for dependency injection compared to IServiceCollection?

Historically, Autofac has provided better support for assembly scanning, allowing me to dynamically load everything I need from the bin directory without modifying my core application. This makes it easier to build plug-in style architectures.

How does Scrutor enhance the functionality of IServiceCollection?

Scrutor enables assembly scanning for IServiceCollection, which is not available by default. This allows me to register all classes in specified assemblies automatically, similar to how Autofac works, without needing to write multiple extension methods.

What are some potential drawbacks of using Scrutor compared to Autofac?

While Scrutor simplifies registration by allowing global scanning, it may lack the granularity that Autofac provides. With Autofac, I can explicitly define how each type should be registered, which can be beneficial for managing dependencies more precisely.

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