BrandGhost

Let's Code LIVE - Building Dependency Injection with Needlr

We'll be looking at building simple extensible applications in C# using dependency injection... With a twist! Needlr is the opinionated package I created for scanning assemblies for types to add into the dependency container for my C# applications. We'll see how I use this for building plugin systems! As with all livestreams, I'm looking forward to answering YOUR questions! So join me live and ask in the chat, or you can comment now and I can try to get it answered while I stream.
View Transcript
All right, folks. I'm just going to get things kicked off here. Get the streams streaming. Get the chat chatting. We'll see what's up. I think the chat's connecting. Good start. Looks like the stream is going nice. Okay, cool. Well, great success. Okay, we're going to be doing something a little different today because we haven't done it in a while. We're going to be coding live, which means you get to watch me mess up a lot, make it look like I have no idea how to program. Um, that's exactly how these things work. been doing it for over 20 years and as soon as I have to do it in front of a live audience, it's like I've never done it before. Hey Devin, thanks for joining. Happy Monday. It is um we're going to be looking at some C code. I'm going to be walking through um this package that I put together called Neler. Not because I am trying to pitch it to people. It's a opinionated framework for scanning for types and that means that we can build plug-in systems really nicely or easily. In my opinion, it's opinionated based on my opinion. So, um the goal is not for me to say, hey, like you absolutely need to use this and this is the best way. And I I hope it never comes across that way. I like don't want stuff I talk about to be like, hey, like my way is the only way. In fact, I want to fully recognize that some people will hate this. That's that's totally cool. Uh but I want to sort of do some uh comparing and contrasting and we can see like well you can be the judge. Um, I want to walk through like building some really simple stuff and we can see how dependency injection looks in C traditionally when you're adding stuff onto the the collection for your uh well your service collection then we go to make a uh provider from that and then we can resolve things and I just want to show you like I don't do it that way. I use all the same pieces but it looks a little bit different when I do it. Hey a random programmer. Thanks for joining. Good to see you back. And yeah, I mean, this is still like an AMA format. I always want my live streams to be AMA. So, if I'm coding stuff and you're like, "Hey, I got a question that has literally nothing to do with what's on the screen," that's totally cool. I will try to make time to talk about it. If you're seeing what I'm coding and you're like, I don't know what's going on or why we're doing this, just feel free to ask. Um, but I'll probably jump into it. I guess I wanted to not miss this like I did last time. I thought it was really fun. I don't know. I thought it was fun when we got to ask AI to build something for us. So, I figured I'm going to ask AI to build something while I do this live stream. And maybe we'll check on it at the end. I don't think it's going to work to be honest, but um we'll check on it at the end. I think it's way too complicated to oneshot it and um we'll see. But give me one sec here. So, I came up with a plan for what I wanted to do. Um so, let's let's jump over to this. By the way, uh if if I ever have stuff that's like being obscured by my stupid face or the chat, just uh let me know. I will try to address it. But, uh I'm trying to watch the chat as well. you can't see my screen set up, but for me to see what's on the screen and being obscured, I have to look like way up here on this part, and that's way out of the way for me. But the chat's right in my face. So, if you're saying something like we can't see, then I will probably notice it much quicker. Um, but boom. Let me zoom in a little bit. I have this PRD file here. And what I did was I was talking to chat GPT before this stream and I had this idea that I will share with you. Um I'm if this doesn't work, this is something that I will go build and I'll make YouTube videos on it and stuff. But what I wanted to do was well let me just let me open this. Okay, we have let me get a little bit more real estate here. There we go. Sound effects and all. Okay, we are going to build a rag system using Postgress. It's going to hopefully probably not, but it's supposed to, maybe I'll say it that way, it's going to look through the lore for the game that I've been building for over 20 years that will never be finished. It's going to go through the lore markdown files and what I want it to do is vectorize them and then I want that to be able to uh support semantic search for us using Postgress and then we're going to have semantic kernel on top of that and that way we're going to have an interface that we can work with where we can ask questions about the lore of this game world and it should be able to tell us with I'm hoping some degree of accuracy But uh I think this is going to be a pretty complicated thing for this thing to build. So I asked chat GBT to make a PRD for us and uh gave it some requirements and stuff. So overall some pieces that I want in the system uh highle architecture. And by the way, I let it drive a lot of this stuff. I kind of just picked some pieces like uh I wanted like I don't like using entity framework core. I'm one of those people. I don't know why. I just don't like it. So, we're going to use Dapper. Um, but I was like, hey, I don't know if Dapper supports all the vector types and stuff with Postgress. I've never tried it. This is it's going to be the first attempt at this for for me. So, if it doesn't work, I just kind of told it in the instructions like if you think it works and you're confident, use it. If not, skip Dapper. But I don't want to use Entity Framework Core. Um, I told it to use Needler. I have a a bad feeling that it will not get the needler usage correct, but the nice thing is that you can still using needler kind of fall back to just normal dependency injection. So, not really a big deal. Told it when it's making plugins to try having single responsibility cuz in the first attempt it like made like in chat GPT it was like here's one plugin. We're going to set up logging. We're going to set up the database. we're going to set like nope just make different plugins for these things please. So I gave it a little bit of instruction there. Um it added in like health checks. I didn't talk about that. I didn't talk about schema migration at all. Um it came up with this schema again. Uh do I care? Not really. It's probably going to change. That's fine. Uh, but I think that there's just a lot of stuff in here and I I'm not really hopeful that it's going to get it right, but I'm curious to see how well it does. Right. Um, again, this is all from chat GPT just kind of like coming up with some some code. Um, one of the things that I told it to to re-examine was when we're asking for lore. This is like the semantic kernel side of things. Um, nope. You're getting blocked right from my chat. There we go. Um, it was like you send in a string question and then it was giving a string back, but it was structuring like a complex string to return. So, I was like, no, just we're in C. Return return an object for us. Um, so couple of improvements there. There's a lot of sections here, but um this is the part that I think will hopefully help it. Like I told it to go uh break down the work streams. Now that I'm reading this, I feel like the work streams are not very detailed. But we'll see. Uh maybe it can use the information from above to make sense of uh workstream. A looks like it's far too light, but we'll see. Uh go a little further. But it kind of builds things out across these work streams. And I told it to pay attention to um what can be done in parallel. We're going to use clawed flow for this part. And then there is a bit of a checklist. So any I don't know. Chat's pretty quiet. Any thoughts? Hey Andreas, good to see you. I I told it to put some exit criteria because I have a bad feeling it's going to do each of these and be like, "Great success." And then it won't even compile, but it'll keep going. So we'll see. Overall, I think it did a good job putting the pieces together, but um I just I don't think it's going to work. But that's fine. We'll uh we'll see. Cool. Let's see. Um Claude flow. Uh we are going to do a um hive mind. Is it spawn? I think. And then I'm going to do the thing where I talk into my mic and it types for me because I love this. Um, use the prd file to create the software defined by the spec. There we go. Um, pretty simple prompt. I was hoping that I could do like basically nothing in the prompt and then have it all in the markdown file. Um, Ben's asking which coding AI are you using for this? I am using claude flow which is an like an like an agent layer on top of cloud code. Uh yes, claude code has like sub aents and you can run parallel tasks and stuff like that. Cloud flow at this point is just like sort of organizing it a little bit uh nicer. It's supposed to have shared memory. I still don't think the shared memory is working, but that's okay. Um so we'll use claude. And then I need to do is it auto spawn? I think we'll see. But I think that's going to kick us off. Okay, we'll let that go run in the background and we'll check in on it later. Now, let's go build some stuff. So, um, no. Devon, have you seen the new AI features in Code Rush? They included a hockey for voice prompting. No, I've not used Code Rush at all to be honest. That sounds interesting. Windows itself has like a whatever. I don't even know what the key is. There's a key combo for it. But um honestly, the I was a little skeptical about two things. One was uh using let me go back to so I can so I can talk. Um because I talk with my hands. So um there's a software that I'm using called Whisper. And I was like, "Ah, this is a gimmick." Like, there's already, you know, speech to text. Why would I use this? Um, I tried it out. It's um Oh, sorry, Jonathan. Uh, on are Mondays here only now? Uh, no. Um, sorry, they're on the podcast YouTube channel. Um, it's I knew this is going to be a discovery problem for a long time. Give me one sec, folks. I just want to put the link into the the chat. So, that is here. That's on Substack. If you're watching it and you want to know where the YouTube link is, it is um it should be on LinkedIn, too. Is this going to LinkedIn? Yeah, it says it's going to LinkedIn. Cool. Um but anyway, it's the live stream for YouTube is on the podcast channel. Uh what was I saying? Oh, Whisper. Um, it's it's like AI boosted and it does a really good job. I am surprised. So, I ended up getting a license for that. And then the other thing I was skeptical about was using a foot pedal, but I have noticed that for the key combinations and stuff, I can't be bothe like I won't press them. I don't know why, but when I have my foot pedal, I can just It's a lot more intuitive. No idea why. I realize it's just it's just a fancy keyboard for my feet, but uh it gets me to use it. So, um whatever works for you. I'm not here to sell you foot pedals or whisper, but that's what's working for me. Okay, so um I got Needler here, and I figured uh I would ask the Oh, discovery problem solve. There we go. Uh, I'd ask folks that are willing to chime in in the chat. If you have ideas for simple things we can go build, uh, we can do that. Otherwise, I'm just going to walk through an ASP.NET Core example. So, I'm just going to start with that, but if folks have different ideas, let me know. Um, we will do uh YouTube. Let's do I'll end up deleting this out of here anyway, but that's okay. Um, Sure. So, this is going to be probably familiar to anyone that has Oh, I'm not sharing my screen. That's probably helpful, right? I just made I made a new project. You didn't see me do it, but I promise you it's just the sample weather application. So, um this is pretty Why is my keyboard not zooming in. There we go. Um, pretty typical for C developers. If you're not a C developer, um, and you don't know what's going on, that's totally cool. But we end up having a couple things going on here. Let me collapse a bunch of this. The idea is that when you're trying to build out systems in ASP.NET Core, we are working with a service collection. Uh, maybe I'll take a step back. We're going to be talking about dependency injection. And when we're building ASP.NET core apps, we have this web application builder. So this builder is to build web applications. So just so you can see it without the var out the front. That is a web application builder. This does have its own service collection for us to work with. And when we use the word service, if you're not familiar with this, I don't mean like literally a running service on some machine. I realize this might be confusing for some people. It's when we talk about a service in this context, it's just like a type that we can work with, an instance of a type that we can play with. So, uh like a logger is a service. Uh you might have um I don't know a database context or if you're using entity framework or that could be a service. It's just an instance to something that we can work with and we call that a service in this case. So when we talk about service collections, service providers, service locator patterns, this kind of stuff, we're just talking about a dependency that we want to use. So hopefully that makes sense. Now, traditionally when we're working in a ASP.NET Core, we do this kind of thing where we take our builder. You can see that copilot's automatically adding some fun stuff, right? So, services and then see how it has all of these methods. You see how little that scroll bar is? You can add this is like the pattern that we use. And the other thing to point out, it might not be super obvious. Um, I'm using a sorry, my resolution on my screen is a little bit ridiculous. So, usually for YouTube videos, the text on everything else is a lot bigger. But um if you pay close attention to this icon here, it's this cube with a down arrow. This is an extension method. So in general, the pattern is that we add things on. So you would say like add, oops, not that word. Um add and scoped. So there's add scoped, there's add singleton, add transient, and then you can add the things that you want to do. These don't exist. I'm just going to let co-pilot kind of make some stuff up. Um, but you just so you can see like we could add controllers. Uh, I just want to show you that this kind of thing if you keep adding stuff um add a repository, right? Like I know these things don't exist, but my my point is that um what ends up happening over time is you keep adding stuff into this entry point. Then what happens is you go okay like so this code balloons out of control over time because you keep adding features into here. I'm obviously exaggerating this but um this can this truly can grow to like hundreds or thousands of lines. That part's not an exaggeration. Obviously, it's not going to be the same things over and over, but um this can get really big. So, what you end up doing is you say, "Well, that's not what we want. I want to extract this." I'm just going to do a local function for the moment. Add cool add cool services. And then usually what we do is we make an extension method for it. So you see how this up here on line three is add cool services. Then we call the builder. What we actually want it to look like so that it follows all of the cool conventions is that we get add cool services. There we go. So this is the syntax we want. Okay. Because then it matches like the add controllers one. So people move out all of these adding of services into their own extension method. So that means we need to do public static class. Thank you. Copilot. So we go add in all of this stuff. Okay. And I'm just going to It doesn't even fit on the screen. So now we have this extension method. Um this part's wrong. So, let me block select. Boop. There we go. Okay. So, obviously this isn't going to compile because I made those things up. But if I scroll back up here, you can see now we have add cool services. It's just one line instead of all of these other lines. Right? But the catch is that this problem doesn't go away. We've just moved the problem because anytime you want to go add new classes, they either belong with the weather stuff and then you go, "Oh, man." Okay. Well, I I'm just This is going to be terrible examples. Sorry. Um, weather logger and then, oh, there was this we need a weather cache, so we made a weather cache. I have to go add it here. Um, and then weather tracer. um you keep doing this pattern where every time you're introducing new things to work with, you just keep stacking them on here and then one day someone has the bright idea where they say, "Hey, it's no longer just a weather app. It's also going to be I don't know who has a fun idea for what else this app could do aside from weather." And let me rename this add add weather services. Any other ideas? It could be a shopping cart. It could be a movie search. I don't know. Like you end up adding more stuff, right? So you're like, well, it's not weather that I'm adding here. So builder services do add uh let's do add singleton and shopping cart. It's really hard to type with this camera in front of my face. Shopping cart service. And then I need my shopping cart. Car rental service. Okay. No, we're doing that then. Um, so what do we need for a car rental service? Car rental service. We need a car rental repository. You can I'm just making this stuff up, right? I don't want to go build all of this right now because um AI hype cycle tracker. Oh, we can add that too. Let's let's add um Right. So, this is what happens especially if you're building stuff at work and you have, you know, um your management because we we hate the managers. I'm a manager. Um you know, you have product managers or your engineering managers like no, we need to go add these things. So we have the AI uh hype service and then we have the AI hype repository and then we need that controller, right? We have to go add these things on to actually controllers are a bad example because I I'm pretty sure with the MVC stuff it will go discover them for you. Uh yeah, there's spoiler alert. Um, but you go add all these things on and then someone's like, "Hey, that's too many things." So, we go repeat the same thing, right? Let me go make a function. Add AI hype services, right? Same thing. Car rental. Okay. So, see, I keep collapsing it down, but I've just moved all of these things. So, like what's the next feature, right? You keep doing this or we have to keep building more stuff and inevitably we come back and we keep adding more stuff onto here. I hate this, but this is where the opinionated part comes in. I really don't like this because uh like 95 to 99% of what I do is almost always the exact same for registering services. When I'm building stuff, it almost never has state associated with it. Um, an exception to that is like like a reference to another service which is like a cache or something like that. But I'm usually not keeping like a list in memory that's like an instance variable or something like that almost never things like that. So I build a lot of things that are singleton lifetime scoped because you don't need to go make another one. It doesn't need to be transient when you ask for it. just get the one that you built the one time because we don't need to go allocate more. It doesn't make sense. There's no state. Um hello and good night to you Garcia. Um so I was like not like out of nowhere I got fed up with this. I just haven't been building software like this because I have not done this kind of thing for years. I just don't like doing it. And that's where Neler comes into play. So I'm gonna maybe delete some of these and show you how we can transform the weather forecast one into a needler approach. Okay. So is everyone following so far or does anyone have questions yet about like adding on the dependencies to the container and how all that works? You might be saying like why do we why are you doing that? Because I didn't really explain that. I just want to pause for a moment for anyone that's kind of like I don't know what you're doing or why. I also need to acknowledge not everyone here is a C developer. So this might be the very first time you're seeing this kind of thing. So um chat is a little bit delayed. Um but like definitely pausing for a moment for anyone to ask questions because it's a good time before we get into changing some other stuff around. There are no dumb questions, right? If you don't know what's going on, that's literally why I'm doing this, just to show you how to navigate this kind of stuff. Okay, I don't see anything coming in yet. You might still be typing your question. If so, keep typing because I will respond and answer. But I'm going to start deleting some of this stuff because we just don't need it right now. Um, okay. So, We got our builder and we have an endpoint, right? This we get pretty lucky here because we can go add this endpoint onto the app. Um, but something else that I like to do, by the way, is I like my entry points being extremely lightweight. What I mean by that is that I mean minimal APIs are kind of a bad example of that because they're very convenient. The fact that we can write a web application that looks just like this in one file is very convenient. But most web apps that you make grow beyond this very quickly. Very, very quickly. So what you might end up doing is something like this. weather extensions. That's not co-pilot. Get out of here. Um, and then we would do something like um public static void, what do I want to call it? Add add weather routes. And this is That's better. Thanks, Copilot. Um, so what I'm doing is I'm just moving this stuff over so that we don't need this record outside here. I'm going to start building this closer to like how I would go build this personally. So, um, we're pulling that out. I'm going to use this actual method. I'm going to cut it right off of here. Okay. I'm going to put it down here. Get rid of the extra dot because I missed that. Uh, and summaries. We don't have access to that. So, let's pull the summaries in here. Um, we can just put this inside. Okay. But we're going to change this up a little bit more, too. So, now we can I'm just collapsing this so you can see more of my screen because it's like this big, but that's okay. So, now we would say, wait a second, we don't have app dot add weather routes. Boom. Right? Like this is a really lightweight little entry point. Very nice, right? But if you recall what I was saying that if we continue to grow this thing over time, we're either adding in like we're registering a lot of routes here. Um this part is not really going away with needler by the way. We just kind of move it. Um, but when we go to talk about these other services, which I'll show you in just a moment, that's where we start to tack on more stuff that continues to grow the entry point, which we will avoid. Jonathan says, "Have you ever made a podcast on project folder structures? Also, do you mind tagging you on LinkedIn post in the future?" Um, have you ever made a podcast on project folder structures? I have not. Um, I I find that I probably have I I guess I would be curious what people want to know about that, Jonathan. So, um, if you have thoughts on that, you don't have to necessarily answer in the chat. You can send me a message on the side, anything you want, but if there or you can answer in the chat if you'd like, but I'd be curious what people want to know about that. Um, the reason that I I haven't really shared that a lot, I guess a little bit with some plug-in stuff, it's because I don't I find a lot of people don't just go build plug-in architectures and that's like all that I build. So maybe it is a good opportunity for me to share more of that. Um, but I find like with with structures for projects, um, it's like it's kind of just like some rough guidelines and I wouldn't um, yeah, Devon said exactly kind of what's on my mind, right? Project folder structures is the stuff of holy wars because I know that someone's going to be very upset just to I just want to and Jonathan, I'm not dismissing your idea because if you'd like to know how I do it, I'm happy to share. But just to show you very briefly this little folder, I know the text is small. This one that says tests. Okay, I don't normally do this in my own stuff, but that's because this isn't really a plug-inbased architecture. This is just like a library to use. Usually, you see how this one says ASP.NET tests and this project down here is ASP.NET. almost always they live side by side for me because I want my plugin to live with my tests for that plugin. So I had to I had them all at the same level side by side and I was like ah this one's not a plug-in architecture. I'm going to I'm going to break my little rule and I made a test folder. Um does it have to be that way? Like I don't I don't know. Um yeah, project folder structure is worse than tabs and spaces. But yeah, honestly, if if you're interested in that or there's certain things you'd want to know, just let me know. Um, do and then your other question, do you mind tagging you on LinkedIn posts in the future? No, like tag me in anything you want. Um, I I appreciate it. I'm fully like fully transparent. Uh, I post a lot more than I actively engage on platforms. And it's it goes in waves. Like if I'm really busy with work, um I like I build brand ghost. I build brand ghost so that it keeps my social media going, but it does mean that if I'm super busy with work that my my actual human engagement to go respond to comments and stuff drops. Like I was I was on call for almost a month straight up until like last week. So um no one like no one forced me to do it or anything like that but um I I had done it and that means that my energy levels are a lot lower. So for me to go actively like go hop onto social media that's not what's going to recharge me. So I absolutely encourage you and anyone else if there's stuff that you want me to check out on social please tag me. Um please you know send me the message. Anything you want I'm happy to look. It's just that because my energy levels kind of come in waves. Um, it might be something that I put off for a little bit. Not because I am not interested in hearing from you. Quite the opposite. Just energy levels. Hey, Danny. Danny, like two months ago, you joined a live stream and I said I owe you a message. I'm coming to speak in Dallas in September and I know what I'm going to talk about. It's going to be plug-in architectures again. Save me a spot. I'm coming. I got to do it. We're going to talk about We're going to talk about this at your Dallas conference. I'm coming. If you will still let me, please. You can't say no in front of this group of people cuz they would they would be so mad. Especially Devon. Devon's going to come after you. Um, just kidding. But I'm going to get back to this. Jonathan, I hope that answers your questions. Um, but yeah, if you want more details on project structures and stuff, just just ask. I will try my best to explain. I can make a video and all that. Okay. So, so far we're not really demonstrating why this is such a big problem. And to be honest, on this live stream, we probably won't grow a project to that size, but I want to start pulling this apart a little bit. Okay, so this is all the same stuff that we had, but what happens over time, especially if you want to have like testability, let's let's pretend these things are more complex. Okay, I realize for a demo on a sample project, like if I don't have this disclaimer, someone's like, you're just adding more complexity. I know, but the reality is the stuff you're probably building in real life is a little bit more complex than the sample weather application. What? Danny, you got you got to have a spa for me. That's actually my bad, though, cuz I put it off for so long. Um, I will send you a message after this. I will do it. Someone will hold me accountable. Um, thanks Devin for for fighting the good fight. Okay, so let's let's split this up into what might look like some some reasonable pieces. First of all, this thing is kind of hard to test. Um, you can do it obviously because this is a really simple application, but if you have more complex logic, generally what I would say is that we don't want to have this kind of thing direct like to test this. I don't want to have to call the web API. I would like to just go check if there's like a forecast provider or forecast service, right? So, let's go make that. Right. So, I'm going to have a forecast service and it's going to generate forecasts for us. And I realize that I got to move this thing out. Let's do that. Okay. So, now we can do weather forecast. Okay. So, we're going to generate a forecast. There's the thing. Oh, but we don't have our summaries. What are we ever going to do? So, we're going to take the summaries out of here. Okay. All that I'm doing is refactoring this code a little bit. Okay. Should be functionally identical. But now we got something going on here. If we wanted to What's going on? What's wrong with this? Oh. Sure, there's an array. Um, so I've just I can't spell. I've just moved this stuff out. Okay, but it's same it's literally the same code just moved. So now what we would do because if we wanted to, we could write tests against this without having to spin up a web server, which is pretty cool. Um, you would do something like this. Okay. And then you would say, well, we could just literally return it. Boop. Okay. So now our API is very very lightweight. Okay. So for example, if you didn't write tests against your API, if you didn't um the reality is like you could still write tests against this thing and you'd be doing pretty good. But you know what sucks? We have our summaries kind of hardcoded in here. Also, I forgot this won't work. Sorry, I'm jumping around a little bit. Builder, this is what we have to do. Remember, we have to add all of our dependencies up at the top. We have to do it. Okay, but this is the part I hate right now. We have this weird summaries array in there. Nope, we don't want that. So, we're going to make another another type. We're going to have our summaries repository. Okay. And there we go. That's a nice little fake repository. And I'm not going to use primary constructors cuz I know someone will get upset. That's fine. We're going to do a public. Thanks, co-pilot. Uh, not quite not quite what we want. Give me a field. Okay, so we're going to pass in our summaries repository. Um, there we go. So, we're going to ask our summaries repository to get the summaries out. This is a terrible example, by the way, but it's simple enough that I can walk through these things. I'm just showing you that we're breaking down the API itself into smaller parts because even though these are very small, very simple parts in your application, these will probably be bigger parts made of many other parts that are composed of each other. So if you're hopefully I can demonstrate how this gets a little bit gross and you can kind of uh extrapolate the impact of that. Okay, but we need to register one more service now. Okay, and the whole point is that if we keep doing this with more types, we have to keep doing this. Oh, but we already have an extension method, right? So let's do that. Um let's do add services. Okay. So now we can just do right. So the whole idea being that like I'm trying to keep this entry point as thin as possible. If you're wondering why I care about doing this so much, I will try to explain in a very simple way. When I am adding new functionality into an application, I want to worry about the spot that I'm adding the functionality to. So just to give you an example, if I'm adding new weather functionality, I want to add the new code and like make sure that I have to just test the new code. Ideally, it's very isolated from everything else. As soon as I have to come back to a common spot to go touch that code, there is now a risk introduced. I'm touching shared code. Even in this case, it's very simple. It's like the entry point with a few lines of code. The point is that I still have to come back to a common spot to touch it. I want to per like this is again my opinion. I want to avoid doing that as much as possible. If I'm adding new weather functionality, I just want to go touch the weather stuff. Okay, so we can keep doing this pattern. Um, just to do one more quick example here, let's pretend we wanted to have a cache inside of our repository. Um, this is obviously already doing a lot of fake stuff, but let's pretend internal sealed, not static, sealed. By the way, everyone's favorite caching library is fusion cache. That's right. We love fusion cache. Jody Denetti writes the best documentation for a uh uh like a a package that I've I've ever read. I hate reading documentation and I enjoy reading the fusion cache docs. So this cache isn't going to actually do anything. We're just pretending for now. But we're going to have a cache. I'm going to use a primary constructor here because I'm being lazy. Um but that means Oh, it's it's unread. Okay. Um, sure. Let's uh my my editor rules are paining me right now. public void. Sure. Let's just let's just pretend. Okay. Okay. So, I'm just making things overly complicated for no reason, but we're going to say, okay, so pretend that this is doing like, you know, either get from the cache or go to the database. But now we have a cache. So, what do we have to do one more time? We add in the cache. Okay? So, we have to keep adding things in here every single time. Again, we're like 20 minutes into this particular part. You probably get the idea. It's getting really difficult for me to start adding complexity for no reason. But, um, if you imagine a more complex application in some of the ones that I build, especially that are already plug-in based, there's a lot of things that get added on. So, to recap, one of the goals that I have when building stuff is I like keeping the entry point as lightweight as possible. The next part is that when I'm adding stuff, I don't want it to touch other parts of the code because I'd like it to be isolated as much as possible because that tells me that's the areas if I want to go test for regressions and pay attention to. Ideally, I'm just touching those spots or putting most of my attention on those spots. It's not like I'm saying by not touching the entry point I'm guaranteeing I won't break anything, but I would dedicate a lot more attention to the spots where the code is changing. So, just to prove that this hopefully works before we get too far, I'm going to run this. Hopefully, it does something. Oh man, look at that. That screen real estate is not so great, is it? Okay, so this is running and I have a web service. Um, let me try to access that over here. What's the name of the weather route? Is it just weather? No. What do we call it? Weather forecast. Ah, hey, we got weather, right? So, like this works. Really kind of simpy simple crappy example, but let's convert this. Okay, so these are the pieces. And what I want to do is show you that I don't need to add extension methods. um I never have to keep doing this ever again because I don't like doing this. But we're going to use Neler to to do that for us. So um let's take this example. I'm just going to pull these dependencies in because it's the same thing. There we go. Um so I have a couple of packages. Um, I have the two that we're going to care about here are the base needler package and the needler uh package that's specifically for ASP.NET Core. And we're going to build a web application in a couple lines of code. It's not it's not going to be dramatically different in terms of number of lines. I just please bear with me. Um, if I were to show you Brand Ghost, Brand Ghost has, I think, 200 projects in it because there's a lot of plugins. And if I tried to build Brand Ghost without using plugins, the entry point would be, I don't know, like a thousand lines long with just like registering classes and stuff would not would not be good for anyone's mental health. So, um, instead, we're going to look at how we can use Needler. Okay. So, I thought that I was going to be clever with needler. I named it needler because dependency injection like a needle and then there's a base type that's called a syringe. It's It's funny. Um I don't know. I am really bad at names and that was the first thing that came to mind. So, in needler. Oh, should I put using What's going on here? Did it not take my Why don't you like it? Oh, I know. Why the project is at a different level? One sec. I knew that was going to come back to get me one day. Um, the question is, is there a full stack on C? I'm not sure what you mean by that question, so I'm not sure how to answer you. I'm sorry. Okay. So, in needler, we have a syringe because that is going to be our fluent builder pattern. And we're done. Almost. It's almost that simple. Um, so what can we do now? Um, we need to get the app. Okay, so that gets rid of this and it gets rid of this. And technically this this did have args on it. So, did I add something for that? Let's see. I I want to be fair. Uh maybe I don't have it on here. Oh, um there's a couple of ways you can do this. So, using options. There we go. And then we can do opt. Why is not working? Come on. It's a function. Oh, it's sorry. It doesn't take them in. So new or we can use the empty ones using CLI args. So this is supposed to be like a fluent builder syntax. So you can do this kind of thing. If you're familiar with link like lenq um then it's kind of like similar pattern, right? So this is now saying we're using options when we create the web application and we just want to use the command line arguments CLI for command line and then pass in args. So now we don't need this line. Okay. And what we're left with is we don't have this stuff hooked up. The cool thing is neither will do a bunch of that for us. But we do still need to do this part manually. Okay. So, we need to get these routes hooked up. And that's fine cuz we can do a internal. By the way, you'll notice I'm using internal. We don't have to expose things if we don't want to. So, internal sealed class. Uh, I seal almost everything because I don't like using inheritance. I don't like object hierarchies. Again, my opinion. So, um, not that it's wrong, not that it's the only way, not that it's just my opinion. So we're going to do a weather weather plugin and this one will be of type I web. What do we need? This was registered on the web application. So I web application plugin. So needler is plug-in based. If uh folks have seen videos on my YouTube channel, I was building a lot of dependency injection stuff with autofac. Autofac uses what's called a module and that's kind of like a it's very similar to how people use extension methods except you don't have to call the module directly. You can scan assemblies for the modules and automatically call them. That's very much what a plug-in is like in Needler. But now I can go do this. Um I want this part specifically. Okay. And then I can say options web application. And then I can fix that up. So this is a plugin that now registers the routes. Okay, we don't need that line now. By the way, I don't need these weather extensions. Boop. Get rid of that. The only thing that we don't have is HTTPS direction, but we can add another little plugin for that. um other fun stuff plugin. Okay, we'll go put that on here. Okay, so what I've done is I've made plugins for these things. Notice how I'm not registering anything um like none of these types are added to the container. Joel says, "There are many correct solutions." That's exactly right. And that's why it's hard for me to talk about stuff that I have an opinion on because I don't want it to come across like I'm telling people this is the only way. It's absolutely not. And that's why I said at the beginning of this stream like some people might hate what I'm doing. It's totally cool. I don't hate it. This is how I like to code. So, um, just to clean this up a little bit because we don't need command line arguments. I just wanted to show you that we can do it. Like this is how much code we have in our entry point. It never has to change. It will always remain two lines long. You really wanted to. Right. There we go. It's one line of code. You can put everything on one line of code if you really try. So the idea is that if I want to keep adding more stuff, I can go build out other plugins and I don't have to come back and add stuff in extension methods and add them to the container. This is done in a way that's automatic based on the rules that I prefer. You can customize those rules, but by default they're the way that I like to do it. And that means that by default everything is registered as the implemented interface and the type itself. I didn't really use interfaces in this example. They are registered as singletons. Again, you can customize that. But I told you at the beginning of the stream or somewhere near the beginning that I like using singleton lifetime because I often do not have state in my objects. the state is like a shared reference to like a cache or something like that. Now, I'm nervous because I think that this is done and I think that this will work, but I'm nervous. So, let's try it. Drum roll. Okay, so far no crashing. Okay, it's running. Oh, wait. I already had this in another window, didn't I? Ready? I'm going to press enter. Oh, it works. Okay, so we Yay. Super exciting. We made the weather sample application. But um the point is that I got rid of the extension methods. I don't have to register stuff onto here because it automatically goes to find it for us. Um we can break this with this, right? So, I'm saying don't autoregister this thing. What happens when I run this? It better not work. Oh, it's probably going to wait for me to try going to Right. It's like I can't find this thing. I can't find this forecast service. And that's because I told Neler specifically, don't register this thing. So, if you wanted to manually register stuff, you absolutely can. I do this in Brand Ghost a lot. I have some more complex things where I can't just automatically discover stuff. I got to set it up by hand. So, I will put this attribute on there and then I will manually register stuff. And if you want to see what that looks like, we could do internal manual registration plugin. And this can just be an I service collection plugin. And then we can say I just want to options on the services add a singleton of the forecast service. Okay. So I can go do that. If I run this now and come back here, this should work. And it does because I told it don't automatically register that thing like I'm gonna go do it for you. So if you have something more complicated, you can absolutely go take care of that. Oh yeah, sorry a random programmer. I'm not sure where the the question was for the do not register attribute, but yeah, if you have other questions on that, let me know, please. Um, but that essentially allows us to to do manual registration. Um what I have been playing around with is like on the syringe class itself and um the web application syringe adding some like helper extension methods for registering things just to make it a little bit more uh I don't know like easy to use. So you don't have to make plugins for everything if you just want to tack like tack on stuff to this. I do this a lot when I am um especially in tests just to give you an example right so I might do like using what do we got um I don't actually have it on here still okay let's do this using post plugin registration callback so see how I can do this right Here I can get rid of this plugin. Boop. So when I'm writing functional tests, I actually really like using I have like a a class that in like in Brand Ghost for example, I have a syringe that I build up with all the things that I want and then before I actually build the service provider, I tack on something like this. and I say like I want you to go add in this new service and usually what I'm doing is I'm overriding like a uh say this forecast service pretend that like actually reached out across the internet to some API and I'm like hey man I'm writing like a unit test here I don't want my code in my test to go hit the internet so I might add a mock in so it would look like again terrible example But um you know I'd have a mock and it would be like an I uh I forecast service. Let's pull that up here. Right. So I would do something like this. Sure. Okay. So I would have something like that. And if you're using theQ framework, it would look literally like that. Okay. And then that way when I'm running my test, I would use the syringe. I would get the service provider. I would resolve the type that I'm trying to to run tests against. And then I can rest assured that anytime it's trying to go out to the internet, it won't anymore because it's going to use this mocked out forecast service. Just as a as a rough example. So, I'm playing around with adding some more helpful extension methods on this. Um, what else? just to show you that some of this stuff works. Um, let's pull this back off. We can use interfaces on things. This is overkill for what we have in this application for sure. But, um, who was using the forecast service? I think it was up on the plugin, right? Uses the I forecast service. Now, we can go run this. I did not change anything about how things are registered, right? I realize that the examples aren't exciting because you're just seeing the same stupid fake weather JSON over and over. Sorry. Um, but the point that I'm trying to make here is that I like being in a position where I can go configure these things and not come back to touch this part of the code. I don't want to have to do that. Okay. So, um I don't know anyone have questions or other thoughts about what we can do with this or why I do this kind of thing. Maybe it made sense and no one has questions. That's cool, too. We could just to go hyper AI plugin AI stuff. Return. Right. We can go add a new route. We don't need the weather forecast service. Um, what else do we want? We want to go do um we had a car rental service. Okay. So, there's two more plugins with routes. Okay. So, I'm going to go run that. There we go. Okay. What was the other route? Right. Um, you can do this kind of thing with controllers already. So, that part's not like that exciting. But hopefully you can see like when I go to build new like features out in in things like brand ghost, I just start writing the code that I want to use and because I follow the same patterns and practices, it just gets wired up automatically and the entry like the entry point here is literally three lines of code or sorry three lines because I split them out. There you go. Um, so for me this is really helpful. Um, I never have to go back and I'm like, "Oh, I forgot to register whatever." I just write the code and it all gets wired up. Um, this will become an absolute nightmare. If you are creating classes with a lot of state and if you want to do that, that's totally fine. But you probably want to control how they're being registered. the default settings that I have will not be good for you because you might say next time I want to access this I need it to be scoped or transient because I need it to live for the lifetime of this web request coming in right like if that's what you need then you don't want my default settings if you have state on those things I don't write code that way singleton lifetime works very well um Brand ghost uses quartz which is a job scheduling framework. If I wanted to resolve a uh job interface if I wanted to quartz actually needs um I think transient lifetime on jobs. Um I use you can see well maybe you can't because the text is small but I use something called Carter for registering stuff. I really like using Carter. Um, it means that I don't necessarily have to write plugins like this. Carter, now that I have Needler, actually, I don't really need Carter now that I'm thinking about it. I was about to explain what Carter does. It's this. Um, which is fine. So, that's cool. Um, I have Carter inside of Brand Ghost, but uh, I noticed that if I'm using Carter, I need to actually exclude um, Carter modules from being automatically registered. If I don't, they get double registered. So, maybe I'll just pull Carter out and I don't have to worry about it anymore. But, u, I do I do like Carter. I think it's a nice, um, it it facilitates what I wanted out of registering API methods. So, um, I thought that's worked really well, but overall, like this is what Needler does in a nutshell. Um, and I don't know, I don't think I have anything else to to add in, but you can do this kind of thing. Uh, just to quickly show you that, uh, YouTube example we just looked at is very much like, uh, like this one, right? Web application is built on one line. Um I just have a bunch of console right line stuff here so you can see um you know if we try to resolve stuff what's happening but it's lit literally like we just looked at right weather plugin weather provider um a more advanced one is here. So, oops, wrong file. But you can see like this has a lot of stuff going on in the entry point. But the cool thing is like if you configure your web application this way, you you shouldn't have to come back here when you're adding new features. So, I can walk you through quickly what this one does. Um, needler supports screwdor which uh is a very popular it's a super popular uh type scanning system. So basically like I didn't like using coming from autofac I didn't like using screwdor because it got me most of the way but not all the way. So, needler is is essentially my combination of what I like in autofac, what I like in screwdor and working with the, you know, the the base dependency injection stuff, but you can use screwdor for doing your type registration. So, that's built in. It is a separate package, so you're not forced to have that dependency. We can change how we want to go look for and sort assemblies. So, in this example, I'm saying only look for assemblies that have uh Nexus Labs or ASP.NET Core App 1 in the name, but you might say all of my plugins are named a certain way, so go look for those. Or you just use a different builder here. So, you go return something that's going to give back Neler the assemblies that you want to look at. You can add in additional assemblies. So, there's some flexibility there. I've done this kind of thing in like test projects where I build this stuff up, but I'm like, "Oh, by the way, here's a couple more for you to look at." Um, the four-weather application changes this syringe into a uh weather application syringe. So, we have some ASP.NET Core functionality. This is one where I'm saying I just want to use a console logger on startup. If I jump into this, right, it's a helper method really just sets up a a logger, right? Logger factory add console set the level, not rocket surgery. Um, this gets a little bit more complicated because I, like I said, I just wanted to show some some things that you can do. Uh, we need a configuration. So by default it will use an empty configuration, but if you wanted to pull in stuff from app settings, environment variables, whatever, there is a configuration callback where you can go set all of that up. If you play with this in the repository, you can prove that it's taking effect by like uncommenting some of this code, right? So if you were to do this and go run the application, you will get different results. Um, otherwise that one's pretty straightforward, but this one has a lot of complex configuration in it. Uh, what else? This one was just uh setting up plugins. So again, like it's just when you look at the entry points, they're generally very very lightweight. And that's my goal with this kind of stuff is that I don't want the entry point to have a bunch of stuff. Unless you need complex configuration like this, then you can do it. But I think that's it, folks. So, at this point, there's something that we should not forget about. If you join the stream late, you might not know, but we said we're having AI build some stuff for us. Do we think that it did it? I don't. Okay. Let's see. Let's see what it did. Okay, the lore rag system implementation is complete. Claude says, "I've successfully built a comp, it has to be comprehensive, a comprehensive retrieval augmented generation rag system based on the PRD specifications. Here's what was implemented." Jonathan Baron, you wanted to know folder structure. This is absolutely not how I would do it. Um, just as an example, by the way, friendly reminder, it's not that this is wrong. It's just not how I would do it at all. Um, I cannot stand personally organizing code by like the groups of things like having a models folder, having a folder for interfaces. No, I can't I can't survive that way. That's totally fine if that's what you love to do. It just doesn't work for me. Um, I much rather have my stuff grouped by features. I find that like within a feature when I keep going deeper, sort of like a layered architecture kind of shows up. So, just as a brief example, let me talk with my hands for one moment. um if I have like vertical slices or plugins that are features. So you know a feature within that feature I might have like the web API the web API calls the business logic the business logic calls into the data layer um the data layer will have like caching and like the actual data access. So I generally find a layered architecture shows up in each of the verticals but my overall project structure is generally like entry point and then uh individual projects for plugins usually. Um cool let me jump back here. So key components delivered. I bet this doesn't even compile, but uh Postgress connection plugin. It's got PG vector support. Sera log, I said put Sarah log in for logging. Semantic kernel with Azure Open AI. Okay. Hybrid search combining vector similarity and Postgress. FTS smart markdown chunking with header preservation content dduping with hashing. Okay, it's got a restful API. Okay. I don't know. Do we do we take a look at it? I'm scared. Oh, okay. Uh, I don't even see a solution. To be fair, this happened to me with the Pokemon thing or it built the whole Pokedex and I was like, "Oh, this is dumb. I don't know. I'm just going to open up the project. Maybe it didn't make a solution for it." I just have very Oh, okay. I don't know like it's maybe it'll work. What's the read me say? We should start with that, right? So, I don't have I'm not going to put in my Azure Open AI key. Copy the example environment. Okay. I don't like Do we try it? Let's try it. Who wants to take bets on whether or not it compiles? I don't think it will compile. We're trying it. Okay. Oh my goodness. What? Okay. Um, it compiles. That is much further than I thought we would get. Um, I need to check what the read me said. Oh my goodness. How are we going to ever see anything here? Where do we What's the end point? There's a health and a an API lore ask. Oh, okay. That's fair. I don't have the environment configured, so that's not terrible. I'm actually amazed that this actually compiled. What'll this do? Okay, it's probably going to complain about the same thing. Um, can we get away with? Probably not. I'm probably going to have to go configure all this, but that could be a very interesting YouTube video followup on the main dev leader channel, which is a great segue. Um, I I'm amazed that it compiled. Um, I have terrible luck with getting that kind of stuff to output. Um, I don't know, anything that that works. So, give me one sec here. Uh, I'm going to sign off on the stream, folks. But, um, I promise you I will get that covered in a YouTube video. It'll be kind of interesting. If folks don't remember from last time, we had uh we did a recipe timeline planner and a net learning kind of uh system where it could recommend videos and things like that, which is pretty cool. But in general, folks, my live streams are generally based on this. Um so this is where my newsletter is. Oh, uh, a random programmer. I quite confident my message got lost in the menu. I'll check on, uh, is it a message or is it a comment? I have not been on to Whoa, whoa, infinity mirror. Um, I haven't been on to check my messages, so I apologize, but if it's a comment, then it's probably miss. I also didn't check my comments at all today, so let me know. I will follow up. Um, but for folks that are interested, this is where my newsletter is. It goes out on Saturdays. I did not release one this weekend. Um I was taking my on call day off on Friday and then I said I'm a little burnt out. I rarely ever skip newsletters and I skipped this weekend and I take it pretty seriously when I skip the newsletter. So I needed to rest. Um okay, a random programmer. I will check. I don't know if I can call you Michael though. I think it has to be a random programmer for forever. Um, but the newsletter comes out on Saturdays. It's an email newsletter. If you don't want emails, don't worry. Don't subscribe. But you can check it out literally just by going to the site and you can see the topic. So, this was last week's um with my dumb face. But, um, the live stream was on the same topic. That's generally how it is. So, that's that needler. This is what we looked at today. If you're interested, there's a link. I got five whole stars. Wow. Um, but this is an opinionated framework. There's the little guy. Thanks, ChatGpt for making the mascot/logo. Um, but it's got documentation and stuff. It's got the examples we walk through. You can check that out. There'll be more YouTube videos coming out on it so you can see kind of roughly how I'm using it. The YouTube channels are the Dev Leader podcast. That's where this is being streamed to on YouTube right now. So for folks that have uh issues discovering where the live stream is now. This is where it will be. This is also the channel where I have interviews with software engineers. Um I talked with Hassan Hhabib not too long ago. Uh one of my favorite conversations I've ever had on the podcast. I got to get my Scott Hansselman one back uploaded here. And I just did an interview with Derek Co. Martin who is code opinion. Um it's really cool because I get to reach out to these people that I really look up to and I'm like, "Hey, let's let's do an interview and they agree to it and then I get to like fanboy out and talk to them." I try to try to act cool though. But um yeah, really awesome to get to chat with these folks. They're all got amazing career stories and stuff. So, if you're interested in hearing about other people's journeys, I find this is very helpful if you are getting started out or you're I like thinking about switching careers and you're thinking like this is impossible like my journey looks very different like check out one of these because everyone has a different journey and I think the more that you start to to realize that the more that you realize like yours is supposed to look unique and that's totally cool. Dev Leader is my main channel, so if you want to watch the programming tutorials, this is the link to it. Um, I got a new intro video with my bald head. It was overdue. I need a new thumbnail for that. But, uh, this channel will be essentially just programming, uh, in C and AI tutorials. So, you can check that out. Especially if this kind of stream was what you were interested in, this would be the channel that I recommend. Usually my my Monday streams are not coding though. So the next channel, there's a bunch of them by the way. So next channel is Dev Leader Path to Tech. I am still overdue on some resume videos, but um I was just talking with my editor today. He had to do a bit of a move, so he's got a handful of videos he's got to catch up on. Um these will get uploaded here, but this is all like resume reviews. People send them in, I review them. They're not roasts. They are literally me trying to help. So, I will call out the things I think you're doing well and the things that I think you can improve on. Again, my opinion as a manager of 13 years. Code Commute is I don't know is Code Commute my favorite channel? It's hard to say, but Code Commute is definitely one of my favorite channels. And the format is like Q&A vlogs. So people submit questions uh either on code commute or like on the YouTube channel or codecommute.com. You can submit questions anonymously and that way that goes right to my email and I will make a vlog entry for you. I'm always looking for code commute topics by the way. When I don't have any that are pending, I just go to Reddit. So if you want your stuff answered, that was code commute was like my solution to people sending me messages on social media and me being like I can't just like answer one-off questions all the time. And same the ré review channel was the solution to people messaging me and being like review my resume. I'm like I'll review it on YouTube if you want. Um then I get to make content. So almost last. I promise we're almost there. I got courses if you're interested. This is one of the paid things. Yes. Um, some people were able to snag this for free at the beginning of the year, which is pretty cool. But, uh, if you're interested in learning C, I have two courses, uh, specifically for getting started. They're 11 and a half hours in total. There's some other C courses, but then I've also paired up with Ryan Murphy and we do some soft skills, career development, promotions, that kind of stuff. So, if you're not a .NET developer, don't worry. If you enjoy the way that I teach things and walk through topics, then there's some courses that you might be interested in as well. Nick Chapsis almost always seems to have a sale on. Every time I stream, at least there's a sale on. So, there's a sale if you want to get a deal. And finally, Brand Ghost, if you're interested, Brand Ghost is what I am building. And Brand Ghost is built using Needler. In fact, Neidler, the code for Needler, I explained this in today's code commute video, which will go out on Wednesday. The code for Needler was me copying and pasting Brando's code over to a new solution and then just chipping away the Brando specific pieces until I had Needler. Then I spent this weekend trying to reintegrate Needler back into Brand Ghost and realized I missed a bunch of stuff. So I added that back and forth and now Brando is running using needler for dependency injection. So brand ghost is my solution that I have built for cross-osting and scheduling social media content. So if you go on my social media platform like uh social media profiles across any platforms the things that I post are all through brand ghost. So, my LinkedIn posts, my uh Twitter, Blue Sky Threads, Instagram, Tik Tok, YouTube Shorts. What else? I don't have Tumblr anymore. My Reddit, I have a Reddit profile. If you want, you can follow me on Reddit. Um, everywhere. If it's a social media platform, we try to support it. I guess I could have looked at the icons, right? I have a Pinterest. Um, so you can check out any of these platforms and I should be posting there except Tumblr. They banned my Tumblr account. I think someone reported me. I don't know. It was really weird. But I had like messages on Tumblr from people. So if you are interested in posting more content to social media, it's literally free, promise. Um, we don't take your credit card or anything because my belief is that if you want to post more on social media, there's lots of tools out there that'll do it. So, we'll just give it away for free. Uh, like Buffer is probably one of the biggest, you know, um, competitors. They've been around since, I don't know, like I started making content in 2013 and they already existed. Buffer has a like a free version, but we just give you all of the platforms for free, so we're obviously better. Um, but yeah, you can get started with crossosting and scheduling for free using Brand Ghost. If you have a small business or you like say you're not interested in being content creator, that's fine. But if you have a small business and you need help with like marketing your stuff, you can use Brand Go to basically perpetually schedule content. And that way you have sort of like this infinite feed of stuff that will go to social media. Brand ghost with the recurring posts is what I use especially when I'm burnt out and I cannot create more content because I don't have capacity for it. Brand ghost will recycle old posts I have and that way I can still share content. So uh that's how I survive social media and it's thanks to Brando. But folks that's it for today. So, um, thank you so much for being here. I appreciate it. I hope you got to enjoy needler, something a little different for the Monday streams and, uh, I appreciate it. So, uh, next week we'll probably be back to sort of normal software engineering topics. If you submit questions on code commute, they can very well end up being the same topic that we we do on the uh, the live stream. So, I recommend it. Plus, I would appreciate trying to answer your questions. Uh, no math questions, just software engineering and career questions. Cool. Thanks, folks. I will see you next time. Take care.

Frequently Asked Questions

What is Needler and how does it relate to dependency injection in C?

Needler is an opinionated framework I've developed for scanning types, which makes building plug-in systems easier. It simplifies the process of dependency injection in C by allowing you to automatically register services without cluttering your entry point with extension methods.

Can I use Needler for projects that require stateful services?

While Needler is designed with singleton lifetimes in mind, you can customize it to handle stateful services. If your services require different lifetimes, like scoped or transient, you will need to manually register those services to ensure they behave as expected.

How can I ask questions during the live coding session?

I encourage viewers to ask questions at any time during the stream, whether they relate to the coding topic or not. Just type your question in the chat, and I'll do my best to address it as we go along.

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