This video is part of a series where we will explore how to create a facade in C# and then use plugins in your .NET / dotnet applications. We will be using a repository as a basis for our facade and then exploring some of the challenges and benefits. Our facade will be composed of multiple plugin sources where we will use Autofac to load them in dynamically at runtime.
When you're done with this video, you should follow up with this one:
https://www.youtube.com/watch?v=33YaRGEsaDI
You can also...
View Transcript
We're going to look at the last video's code and we're going to start to actually separate that facade out with the repositories that go into it into different plugins. Then we're going to load that up with Autofac and we're going to explore a pattern that I've been using for a little while that I haven't really liked, but I've just come up with a solution for improving it. So, if that sounds cool, please give the video a thumbs up, subscribe to the channel, and let's jump right into the code. Okay. So, what I'm thinking about doing here, just to make the naming convention a little bit more straightforward, I'm going to start breaking out uh some additional projects here in the solution to show the isolation that we have, but I'm going to structure it such that we can tell which uh way the dependencies are
kind of organized. So, I'm going to change this to actually be our entry point. I'm just going to call it example program. And that's going to be our entry point. The next thing we're going to have is um I'm going to just make up stupid names, but I'm just going to have an API project, the My Object API. Again, terrible names, but just to kind of prove a point here. And what we're going to do is move over the Myobject and I repository into this. And then, so that's the API. Now, let's get into actually creating a couple of plugins. So, what I'm going to do is add a new project here. And we'll just again names are going to be not a strong suit here. Um, plugin one. And usually what I would do here, I'm gonna actually just do some copying and pasting
because I want to save some time. But usually what I would do is I might have something like a reusable uh repository pattern that I want to use across plugins and put that in a common spot. Um, but if you remember my example from earlier was saying sometimes we're talking about repositories that maybe I want like a uh a SQLite adapter. I want a a MySQL adapter. Um, perhaps in your application structure, you only have ever one uh SQLite adapter set up and a one MySQL adapter ever set up and you wouldn't need to share this implementation anywhere. In our case today, we do want to share it, but I'm lazy. We'll have one here. And just to prove a point too, we'll say in memory inmemory repository or or plug-in one. Okay. Um, I'll rename the file too. And then we need to get
these dependencies brought in. So, I'm going to pull over the reference from my object API. And that should allow us now to access these. So, now we have one plugin done. We're going to go ahead and make the second one. And what I'm just trying to illustrate here is that we're going to have these in separate assemblies and then at runtime dynamically load them and take advantage of the data in both spots in a seemingly automatic way. Um, and it's how I love writing software. So, okay. And like I said, we're going to basically just copy this into plug-in 2. Now, we don't need it in the base program. Excellent. We got to do the same thing where we add the dependency to the API. Okay. So now we have two different imple imp implementations. Um they take in a set of objects. Great. They
meet the same interface. Awesome. And if we go back to our program, obviously this isn't going to work anymore. We want to be able to dynamically load this stuff. We're going to use Autofact to do it. And uh we need to have um basically runtime loading of these two DLS that we just created projects for. So you can see I have access to I repository which is great but this part isn't going to work anymore. Okay. So how do we go about doing that? Here's where we're going to uh pull in autofac. If you're new to autofac, there's tons of resources online about using autofac or other dependency injection. You might see di um container packages that you can use. Autofac is my personal favorite. I'm going to be glossing over some of the details of that. Um, but I will show you how I
leverage it in my setup here and then how I've kind of tweaked that recently. So, let's go ahead and get that added. We're going to go over to our entry point and I'll install that. So, now we have Autofac available to us. And how that will look is you have to, again, I'll gloss over it a little bit, but we'll have a container builder. And this is the part um the object that as it suggests it builds your dependency container. It's a container builder. And um so we'll do something between that um constructor call and then this line here where we actually build it. Okay. So we'll do something in between the uh that part. But how it's going to look is that we would say um container. Usually you might use a lifetime scope and other stuff in here. I think uh just to
save a step. Here's how that would look. So you saw like this will compile now, right? There's no red squiggies anywhere. No errors in my Visual Studio. This will compile, but we actually deleted all the code out of this entry point program that's actually responsible for putting the data in here. So um actually, if I go to run this, it's going to blow up. So let's run it and prove that. and it's going to complain that there's actually no repository that's been registered anywhere. So yes, the facade is still in this um this project, but it's not registered into this container. So I'll show you how I like to do that. Um generally I make a new module. This is not an example of a good name. So, we're going to have a public sealed class here, and it's going to implement a module, which
comes from autofac, not the system.reflection nameace. You don't need to call base.load. I'm pretty sure that's in the documentation for autofac. So, we get rid of it. And what we'll do on the container is we will register our type, but it is called my object repository facade. And then we're going to do I generally use as implement as implemented interfaces a lot. There's arguments for and against kind of calling out this versus um specific interfaces. I generally like doing this personally. Um if you have a different opinion and you have examples of where that's um caught you off guard, you know, comments are open, so let's hear it. Would love to hear. Um, and then this is these three lines in general are kind of my common pattern for autofac. So now if I go run this, what's going to happen? Is this going to
solve the problem? Well, no, because we actually have to go do the thing with the module. So right now because we're we haven't started loading the plugins yet. Um when we go to work with this container builder, we can do register module test module. Okay. So we can do this for now, but we're going to want to change this a little bit and I'll explain in just a moment, but we're going to want to scan our output directory to load in um DLS and such. Now we know that our uh facade is going to be registered. We'll build the container. We will resolve the repository and try to ask it for stuff. But will it work? No. To explain what's going on here is literally how autofac is trying to resolve dependencies is it says you want an i repository. No problem. I have one
registered. It's the facade. to make the facade, I need um all of the other. I use the word other. It doesn't know what's other. It's I need all of the I repositories that are registered. And then it tells itself, okay, no problem. I need to make a my object repository facade. So, because there's only one, it's a circular dependency. And the trick though is that even once we add in the other plugins, right, once we load those, it's still going to have a dependency on itself. And it's because it's using the same interface. So, I'm about to stop um debugging here, and I'm going to show you how historically I've addressed this. It's really bothered me, but it's worked really well. So, it was kind of like if it's not fixed or if it's not broken, don't fix it. Um, it's just ugly. But I
I'm going to show you it and then we're going to show the tweak to it, which of [snorts] course we'll do in the next video. So, if you have any thoughts or questions about how we were leveraging Autofact to load plugins or if you've been using different dependency injection frameworks to approach this same type of thing, let's hear about it in the comments. So, thanks for watching. Please give the video a thumbs up, subscribe to the channel, and I will put the link to the next video right over