Autofac Delegate Factories & How to Decouple Types
July 16, 2020
• 1,244 views
In this video, I discuss how and why you may want to use delegate factories in Autofac. We go over what delegate factories let you do, what I dislike about the pattern, and a pattern that I use to overcome some of the things that I dislike!
If you have your own ways to address this I'd love to hear about it!
My Social:
LinkedIn: https://www.linkedin.com/in/nickcosentino
Blog: http://www.devleader.ca/
GitHub: https://github.com/ncosentino/
Twitch: https://www.twitch.tv/ncosentino
Twitter: https...
View Transcript
i wanted to put together a video today to talk about um this concept of delegate factories and autofaq and i'll show you an example of that i'm just going to jump over to an auto fact module here actually i should show you the classes that actually leverage it but essentially a delegate factory in auto fact is a mechanism that you can use to construct a type using this delegate and essentially auto fact because if you're using auto fact registrations it's able to figure out that like if you can see that this constructor here takes in one parameter and my factory doesn't take in any parameters auto fact through the registration is able to figure out that when someone calls um you know invoke on this factory method then it should go figure out behind the scenes that it needs one of these dependencies and it
wires it up so there's a couple of reasons why these can be helpful a really good example is if you had something like i'm just going to put this on a new line here if you wanted to do like string cool name um and pass that in you might be able to use auto fact to register one of these dependencies so i have them it's something called a string provider it's a pattern i use um and that might be you know like a single instance kind of thing you register it once and whatever there's no um no state that's changing so great and it's every time you make one of these view models it will always take in the same instance however you might want to be able to make this view model and pass in the second parameter and it's always going to be
potentially something different every time you construct it so a way that you can get around that is you could do something like oops something like this where as long as you have access to this factory method all that you need to do is provide this second parameter right and autofact knows based on the registration that it will go figure out this other parameter for you um so it's kind of cool because it gives you this hybrid approach of being able to use some of this auto fact magic to do this resolution for you but at the same time giving you some some customization for how you're constructing things so that's one reason why they can be kind of helpful um the other reason i'm just undoing all that um the other reason they can be kind of helpful um is that i have situations where
um for a lot of the things i use auto fact for i'm constructing them once they kind of exist for the lifetime of the application or for the lifetime of some part of the application that's great um but there's sometimes these instances where i need to make like little call them like one-off instances and they're short-lived but when i do that i want a new instance every time so i'm not creating it at the beginning of the application i need to delay the creation of it and um i probably want to make more new instances of it um so in this particular example that we're looking at that's exactly why i like i have a factory delegate method here for this thing so the situation that i came across today when i was refactoring some code for uh the application we're creating uh in xamarin
forms was that i have something that shows a pop-up to the user and that pop-up has a view and it has a view model associated with it but every time i want to show this pop-up i want to make a new view and a new view model so that's kind of the thing that i'm working through here but the reality was that you know this string provider is always going to be the same instance it's really just almost like a like a constance type of uh class i just hold some strings for me later i'll have them localized and all that kind of stuff but for now it's really just a few properties with constant strings so it's always the same however i do need to create new instances of this view model and pass them into a new instance of the view as well
right okay so that's why i have a factory method here i mentioned as i was talking through that i also need new instances of the view so i need to use a delegate method or a delegate factory like this on the view as well so i'm going to jump to that and what you'll see here let's ignore this constructor for now um the construct that i'm more interested in is this one here it takes in a view model and a toast service so here's another example where the toast service in the constructor it will always be the same service for the lifetime of the application however um because we're making new view models when we go to show this pop-up i need to pass in the new instance of the the view model so because this pop-up page itself is not created at the you
know the beginning of the lifetime of the application it's created later and i want to make new instances of it um it will also need a new instance of the view model to go along with it so i needed to be able to say since i'm making a new view model um i'm going to pass that in here on this factory and like i just explained previously this toast service i'll highlight that it does exist for the lifetime of the application so auto fact will handle going to resolve that dependency for us which is great okay so the the code that wants to use that or maybe i'll show you what the module looks like first um specifically for those two things so when you're registering things for these these factory methods you just use i'm just going to move them down here so they're
separate so you can see them because there's some other stuff on here that i'll come back to um these two things right here that just have register type that's all you need along with your delegate methods so i'm going to jump into the the definition of these we've already seen them but right so this first class we looked at and you can see it has this uh delegate factory method here important to note uh because this is going to be part of the topic of the conversation today is the return type must as far as i know i haven't seen a way around this so if someone knows please let me know um the return type of this has to match your type that you're working with here right so i cannot do this and have everything work i can't return the interface off the
factory which is which is what i want to talk about today so um i'm going to go back to the module and we'll look at the pop-up one just to kind of prove oops so there's two two spots here because it has the code behind and the designer but you can see this is the other one that had this delegate factory right and you can see the return type is also the same as the class cool so that's what the module looks like um specifically for registering things with these factory methods now i want to look at the the part of the code that's going to use that and that is my my navigator class so i use i have this pattern that for showing pop-ups or or navigating through the application i have this thing called the navigator or pattern i guess that i
use and it's just responsible for handling um you know set it like basically setting up the state that you want to show on the screen that you're about to navigate to or the pop-up you're about to show gets that all prepared and then either navigates you there or puts the pop-up up for the user so um i do have some code commented out because i'm going to come back to that um but what we're looking at here i've only i've so we have two factories that we wanted to deal with i've i'm showing a hybrid of the two things i want to talk about but essentially sort of i don't want to call it the problem but the thing i didn't really like is that when you go to use these factory methods with autofaq your new type so my choose location navigator one of
the dependencies that will get passed in through auto fact is this delegate method right and the other one i'll just quickly change to show you is this one oops i have the wrong name choose location pop-up page naming is fun um right so auto fact would figure out because of those type registrations that it could pass in these two factories which is great and then this choose location navigator would receive that when we go to register so if i go back to the module you can see i register this type choose location navigator so when we resolve it later um like i said autofaq will know how to pass these things in for us which is great because now we can go to use them later okay so to use these factory methods it's literally just a delegate right so the one had no parameters
which you can see here right we're making the view model it took no parameters so if i jump to that method right you can see no parameters on here at all i'm just going to change up some of this code here so we can i kind of left it as a hybrid like i said so because i could illustrate some things better but um so if we wanted to make the view i'm just gonna put some extra w's on there so we don't get intellisense getting all upset um you also invoke this one but it takes one parameter which is the view model right and just to prove it so this is the pop-up factory if i jump to that just like we saw earlier it does take this one view model cool okay so what's the problem why am i making this video what
am i here to complain about today and really it's nothing that crazy it's just that i am not a huge fan of um when i'm trying to separate out implementations from interfaces and things like that i'm not a huge fan that um this class choose location navigator now has concrete dependencies on these two other classes okay so really it's it's a pretty minor thing and i can imagine in more complex uh applications or systems that this could become a bigger problem uh but it started like i saw it creeping in here and i was like i wonder if i can address this so the yeah the thing i don't like is that this class you can tell like strictly if you're not if it's not totally jumping out to you just look at the color of the uh of the things that are in visual
studio here so these are two interfaces right i have an eye pop-up navigation uh interface literally it's an interface and what i'm saying by defining it like this is this class does not care about the implementation of this right so someone later on can go um change part of the application to register a different implementation of eye pop-up navigation and this class should not care the same thing with this i event tracker right right now in the application there's only one implementation of it right but i'm by defining this um dependency here is strictly by the interface i'm saying i don't care what the implementation is as long as it meets this api this class will be happy however we get to these two things and for the most part like this factory delegate is just a signature that says like you know i don't
care but but it could right it it lets us leak in some some sneaky things i guess is what i could say and i'm going to try to show you an example of why i don't like that and then how i moved around it so the first thing is like as i said we you can you can clearly see that because these are not interfaces here i now have a dependency on these two types these two concrete types explicitly not a huge fan of that um so that was the first thing that i was like ah like if i can avoid that i'd like to and i'm going to show you with a bit of a contrived example just why i don't like that so um right now if we were using this properly you know let me see this this thing down here i'm
going to comment out the rest of this code because we'll come back to it but this is essentially what it was trying to do for the most part and it's not pages i guess i can name this a little bit nicer now so what we were doing was making a new view model passing into a new view and then telling our pop-up navigation um interface like go it says push async which is essentially push this pop up to the top of the pop-up stack so the user will see it and true is just so that it animates so really something simple here um so you know why is it a problem well you can't like it's not going to show in the in the recording but when i hover over view model here the type is it and it's not going to be as obvious
because you can't see it but it says choose location view model which sounds right however the fact that it says choose location view model and not i choose location view model means that this thing here we have knowledge of the concrete type that's being used okay so our code now has access to a concrete type for viewmodel and if i hover over view again you can't see it in the recording but uh it says choose location pop-up page it is not the interface of it and it's not um this one's a bad example because this other pop-up navigation thing here um not something i wrote and it it does actually require a concrete type however it requires a base type and this pop-up this pop-up factory that we're dealing with here actually gives us a more specific type than we need to know about so
why is that bad okay um it's again this is gonna feel a little bit contrived but this is one of those things that if you know about it you can prevent it um you can prevent some some situations in your code base where you're like oh crap like um we started to get a bit of spaghetti code in this one spot now we have a couple of uh you know um dependencies that are leaked through and like refactoring it's gonna be tricky um and so let's kind of step through that i'm gonna go to this choose location view model and for the most part there's a bunch of stuff on here i'm going to collapse it all so it's a little easier to see all at once i'll expand it so we have a bunch of properties you know it has a latitude a longitude
center a formatted distance that we can show in the ui um just the numeric distance man like there's a bunch of stuff on here and for the most part um these should match what's on the interface okay so if i jump to the interface you can see that a lot of those properties ideally all of them that are public should be met on this interface so what's tricky about that is that i could come through here and i could go public string nyx sneaky if i could spell nick sneaky property right now i have this thing on here and what that lets us do on this navigator is we can actually access it here which isn't like if you're reading this or like reading this code or you're watching this video you might say okay well that's really not bad like who cares um and
you know in this example it isn't bad there's nothing really wrong with this it's just the fact that this class choose location navigator now has knowledge about a concrete type that's really all i'm trying to get at is it has knowledge of a concrete type and when i'm designing uh you know classes um in systems i try to separate that as much as possible i don't unless they're like super simple what we call like a dto or a data transfer object um that has like you know it might hold like a like a string for someone or a couple of numbers or something really simple um that's not mutated unless it's something that simple i really don't like things having knowledge about other concrete implementations so the fact that i have that here bothers me um again really simple example pretty contrived however i do
think that there are examples in real code bases where this kind of thing happens where you have a class that depends on another concrete implementation of another class and uh you can run into some situations where sort of some of these details are leaking through and people have access to things that maybe aren't on you know a public api like an interface okay so that's the thing i wanted to overcome how did i do it well um you probably saw a little bit earlier before i was uh trying to delete some of this code but what i had done um and for sure like again reading through this code or watching this video you might go oh this feels like overkill like i don't want to have to do that totally get it um i somewhat enjoy taking patterns to a bit of an extreme
um because to me it's kind of cool to just like uh to work through some constraints and be like if i really want to avoid you know this class depending on other concrete classes how can i do it it's not to say it's always the best thing to do it might be overkill in some cases um totally get it so i'm not trying to push like some agenda like that but how could you get around it so you saw that i removed those two delegate factories and i put these other interfaces in place so what i've actually done was i made dedicated classes and dedicated interfaces for those factories so if we jump to the view model one this view model one literally what i'm doing is i'm taking a specific factory so it has one single purpose and it's going to construct things and
i've moved that that dependency i didn't like strictly into this factory so now it's in one spot that's dedicated to creating things so to me um i talk about this uh you know with my colleagues and stuff like that about like if you're it's gonna sound a bit exaggerated but when you're dealing with like crappy code or a crappy pattern you don't like the more that you can kind of hide and um move that you know air quotes crappy code or crappy pattern into one small spot and isolate it the better um the more that you have a crappy pattern or something you don't like that's like spreading out through your code base you're kind of creating this future problem to work through so what i've done is i've moved you know this problem or this pattern i don't like of a concrete type right
depending on another concrete type i've moved that to one spot and then i made a dedicated interface for basically constructing these okay and if i go to the other one it's very much the same all right so i'm going back into this other new factory i tried to and i didn't like the shortcut um go to definition oh not what i want go to the implementation there we go so it looks like looks similar right where i have a concrete type depends on another concrete type and then uh you know a dedicated method to creating things so this this example was the one i was saying i'm not a huge fan of it because it still returns another concrete type however um this is because i'm interfacing with another third party uh library that requires that i deal with these classes there's certainly ways around
isolating that problem or you know pattern i don't like i don't like using the word problem it's not really a problem um but uh isolating that uh pattern in a different way uh however um for what i wanted to accomplish it was really the focus here so highlighting these lines right i have a specific type that depends on one other specific type and then working through that so if i go back to my navigator you can see that um there's a bit more code here because that other uh delegate factory that i was showing like i had it reduced a little bit so um it wasn't a totally fair comparison but essentially it looks like you know this resembles it a lot closer with this other little event tracker thing that i had left out um so it looks mostly like that um now the
the cool thing here is that um did i leave it on the view model uh nick's sneaky property right it's still here right so if i tried to use that on the view model now it's not there and the reason it's not there is because this factory again you can't see the intellisense as i'm uh as i'm hovering over stuff but if i go to this method it returns the interface it does not return the concrete type for us so when we go to use it on this line here i only have the interface i don't i don't know that this is a concrete type that is choose location view model i only know what's the interface for it right so because this property here was never put onto the interface we can't access it which means that we can't kind of uh bleed through
or leak like implementation details that weren't meant to be exposed if we really wanted it to be exposed we should probably put it on the interface or part of the public api uh that other things can see so that's sort of my argument for for why i like this approach better um it means that i've like i said i isolated where i don't like that pattern right so these dedicated factory classes um and then my calling code doesn't have to deal with those uh patterns that i don't like so if i jump back to the module that we looked at right in the beginning i'm just going to undo a bunch of this to show the organization the code a little bit better for how i liked it um what i've done was i put the pop-up page with its corresponding factory i did the
view model with its corresponding factory right i'm still using register type on these ones with nothing else because um this will let auto fact wire up that delegate factory for us for each of these this one and this one and those delegate factories get passed into these concrete types here respectively because each one depends on the factory of these other things and then these are registered by their implemented interfaces and if we jump into the navigator you can see that i'm only requiring the interfaces right so we think back to right near the start of this video i was saying that one of the things i did not like was writing code that had a concrete type depending on more concrete types and now that's gone away at least here i've isolated the pattern i didn't like to a smaller more specific spot so that's
i think mostly what i wanted to talk about today so if you if you found yourself working with these delegate factories in auto fact um and you weren't a fan of you know those concrete types depending on each other this is a pattern i've started to adopt to work around that um don't want to say that this is you know something you have to do or that it's the only way that you could accomplish this um this is what i've come up with and started using and uh i do like it um i like that i don't have these concrete types uh leaking through in here when i'm creating these things i could imagine there's situations where you do want to be able to do that you know in a particular class that you want to modify some other class you have knowledge about i
can't think of a good example but maybe you want to be able to do that and then maybe you return that um as an interface to someone else so you're kind of masking the fact that you had some extra knowledge about the class you were dealing with to return a you know an interface of it um so i i suppose there's probably some some cool sneaky things you could do that way but um yeah this was my approach we're trying to to minimize that sneaky behavior so thanks that was just a short video that's just what i wanted to touch on today
Frequently Asked Questions
What are delegate factories in Autofac and why are they useful?
Delegate factories in Autofac are mechanisms that allow you to construct types using a delegate. They are useful because they enable Autofac to automatically resolve dependencies for you, while also allowing for customization in how you construct instances. This is particularly helpful when you need to create new instances of a type with varying parameters.
How can I avoid concrete type dependencies when using delegate factories?
To avoid concrete type dependencies, I recommend creating dedicated factory interfaces and classes. By doing this, you isolate the concrete implementations within the factory, allowing your main code to only interact with interfaces. This minimizes the risk of leaking concrete type knowledge into your application, which can lead to tighter coupling and harder-to-maintain code.
Can you give an example of when to use a delegate factory?
A good example of using a delegate factory is when you need to create short-lived instances, such as view models for pop-ups in an application. Each time you show a pop-up, you want a new instance of the view model, while some dependencies, like a string provider, remain constant. The delegate factory allows you to create these new instances on demand without cluttering your main code with concrete type dependencies.
These FAQs were generated by AI from the video transcript.