Are events in C# even relevant anymore?

2024 ж. 9 Мам.
165 688 Рет қаралды

Check out my courses: dometrain.com
Become a Patreon and get source code access: / nickchapsas
Hello everybody I'm Nick and in this video I will explain why I think that events as a feature in C# is obsolete and how we can implement the same event-like mechanism in a modern and elegant way.
Timestamps
Intro - 0:00
What are events and how they work - 0:20
A backend service example - 5:28
How I implement events - 11:05
Don't forget to comment, like and subscribe :)
Social Media:
Follow me on GitHub: bit.ly/ChapsasGitHub
Follow me on Twitter: bit.ly/ChapsasTwitter
Connect on LinkedIn: bit.ly/ChapsasLinkedIn
Keep coding merch: keepcoding.shop
#csharp #dotnet #events

Пікірлер
  • And for those wondering, there is an Rx video coming. The approach in the end is just one example of a safe and easy alternative. Not a goto for everything event related.

    @nickchapsas@nickchapsas2 жыл бұрын
    • I've been using Rx for a couple years now and really like it, especially for lots of async I/O calls. The big challenges are: 1) In the java ecosystem blocking threads is a basic assumption, including specifications like servlet and jdbc. 2) Its a really different way of thinking. Since everything is immutable even things like loops go away! Kotlin, but i think most will get the gist: Flux.interval(Duration.ofSeconds(1)) .map { object { val guid = UUID.randomUUID() val time = LocalTime.now() } } .doOnNext { println(it.guid) } .filter { it.time.second % 5 == 0 } .doOnNext { println(it.time) } .take(10) .subscribe()

      @adambickford8720@adambickford87202 жыл бұрын
    • Can’t wait for RX! After using RSJX, wanted to give it a shot in NET too

      @frotes@frotes2 жыл бұрын
    • Please notify me!

      @teodorchirileanu@teodorchirileanu2 жыл бұрын
    • Hope this one is still upcoming!

      @frotes@frotes Жыл бұрын
    • @@frotes I second this!

      @austinescobedo5006@austinescobedo5006 Жыл бұрын
  • I fail to see how this is even a problem of the event system, and not a problem of the design of the application. The BackgroundService is running an infinite loop and holding a reference to _one_ TickerService (so it's not transient!). The TickerService is holding a reference to _one_ TransientService (so it's also not transient!). An Instance of the TransientService has _one_ Id, which stays the same. Either, make your BackgroundServce be newed up every time, or, make the TransientService not always return the same Id. It goes to show that the in-built events are actually a glorified form of calling a method and pretending not to know about it. You haven't made this completely clear; by putting event and subscription into the same class, you have skirted around the issue that the subscriber has to have a reference to the publisher to be able to subscribe in the first place. But note that in UI applications (Windows Desktop, UWP, MAUI) applications, you usually by all means want synchronous events (INotifyPropertyChanged for one). If you sometimes want an event to do something asynchronously, you will make that explicit.

    @jessicafrankston7155@jessicafrankston71552 жыл бұрын
    • The way this is used the handlers are acting as closures capturing the "transient" object so it won't changed with any subsequent calls, the notable difference here is that with events you attribute a function (which becomes a closure with when values are embed it in it) as a handler, while with mediaR, you pass a class which gets instantiated every time thus triggering the transient service lifecycle

      @jjdd1211@jjdd12112 жыл бұрын
    • @@jjdd1211 I can’t see what the closure does change here. The transient service anyway is injected in the constructor of the dependent class, so you’ll get a new transient service instance only each time this constructor is called.

      @xouxoful@xouxoful2 жыл бұрын
    • @@xouxoful that's exactly what I am pointing out, using a class level value and passing it into the callback, you are capturing the instance of that value into the callback scope, you'd have to instantiate the transient service inside the callback, which isn't anymore expensive than the alternative

      @jjdd1211@jjdd12112 жыл бұрын
    • Ya I really fail to see what problems this is solving or why it is better. The rationale is just that it is "modern", but that is not really something you can define. I do mostly UI code, and Actions/Callbacks/Delegates/Events are definitely the ideal way to de-couple components. Even if I could change the framework... why would you? And if it is obsolete on the backend, why?

      @ShawnBlais@ShawnBlais2 жыл бұрын
    • I agree. I was originally intrigued by this video and failed to see a problem that was solved by removing events. The app printing the same guid repeatedly was the functionality I expected given how it was coded. I also do not want asynchronous events. I dislike a lot of async C# code. Far too often it is completely goofed by programmers and causes way more issues than it solves. If something fires an event that would cause some long processing, then on the event handling side I would make it async. It's always easier to make synchronous code async vs the other way around. With that said I generally like Nick's videos and I'm still able to learn a lot despite being a .NET developer for over 10 years.

      @nick440@nick4402 жыл бұрын
  • That blur at the start 😂 I’m curious

    @Myuuiii@Myuuiii2 жыл бұрын
    • Video used to have a sponsor and the write line was saying “Thanks ”, but I decided to not go with them so I blurred it. That’s why my website call-out is from another video too

      @nickchapsas@nickchapsas2 жыл бұрын
    • Makes sense, I was thinking "What kind of insidious nonsense are we writing to the console?"

      @Gruggo@Gruggo2 жыл бұрын
  • In Unity, event driven architecture is very useful to reduce dependencies between various components, such as UI, managers, controllers etc. It is also one way to prevent the use of Singletons.

    @Haapavuo@Haapavuo2 жыл бұрын
    • Highly recommend implementing a message broker / mediator into a Unity project to allow communication between systems without the need to be depdendent on one another.

      @Wobling@Wobling2 жыл бұрын
    • As someone who will be starting to use unity soon I appreciate these comments!

      @dahliaspumpski5837@dahliaspumpski58372 жыл бұрын
    • I am going to second Atoms for Unity and would even suggest combining it with Reactive programming using UniRx

      @Artmos@Artmos2 жыл бұрын
    • @@Artmos I hate doing any referencing in the inspector since that will make debugging VERY HARD and annoying in bigger projects... You cannot see in a feasible way whether some function is called, asset referenced etc. That is why Atoms is a no-go but UniRx might be nice.

      @Haapavuo@Haapavuo2 жыл бұрын
    • @@Haapavuo I think that's personal preference. I really like having my components decoupled by using ScriptableObjects. I guess if you don't like that, another solution could be a dependency injection library.

      @Artmos@Artmos2 жыл бұрын
  • Nice try! But no way, Nick, you just replace Observer pattern with Mediator (some simple kind of), and say - Events are deprecated. Built-in events mechanism allows to implement push and pull notification strategies, and in case of complex systems you have to mark your classes with redundant INotificationHandler + memory traffic is probably bigger. So, there is space for discussion here, but not for loud sounds sort of "Events are deprecated". So personally for me - don't worth it. And thanks for nice content, anyway. Keep coding.

    @ryanlashkevich9615@ryanlashkevich96152 жыл бұрын
    • Events, the observer pattern and the mediator pattern are all separate things

      @nickchapsas@nickchapsas2 жыл бұрын
    • Events is a built-in observer pattern. Similar to IEnumerable (Iterator pattern, but implemented, actually better than officially described by GoF). My imho.

      @ryanlashkevich9615@ryanlashkevich96152 жыл бұрын
    • I agree. Events have and ever will have their place in the .Net world. They are fast, lightweight, easy to use. If one doesn't understand why an object gets captured in a lambda, then pulling a blown up nuget package and introducing tons of micro classes with dependencies to that nuget package won't help them either

      @wobuntu@wobuntu2 жыл бұрын
    • @@wobuntu Agreed! Maybe I'm just bad at C# but for my front-end use cases in Unity Actions and Events do just fine.

      @jonathandunn9302@jonathandunn93022 жыл бұрын
    • @@jonathandunn9302 I mean he did specifically say in the video that the context of the video is backend services, not front-end work like WinForms and UIs etc.

      @gnack420@gnack420 Жыл бұрын
  • I wrote something, inspired by Aurelia, called EventAggregator that is this same thing. It has been easy to test functionality that only happens when an event is published too. It's been tough since the team I'm currently working with is stuck on events but are slowly starting to see how easy event aggregation is to use in comparison to wiring events all over the place. Plus...you can have two things working together without needing to know of each other's existence. Both components have a dependency on IEventAggregator that ties them together. Just like with anything event related...have to make sure you clean up after yourself and unsubscribe from events when they aren't needed any longer. I'm a big fan of this approach to domain events.

    @logank.70@logank.702 жыл бұрын
  • Good timing. I happen to be dealing with this exact thing right now. Thanks!

    @R.Daneel@R.Daneel2 жыл бұрын
  • I have been enjoying Observable for a while, between Reactive Extentions, Reative UI, etc. I also enjoy F#. From what I recall, in F# events can be subscribed to as observables.

    @JonathanPeel@JonathanPeel2 жыл бұрын
    • I expected him to talk about observables are they are actually that are evening used to replace events. Mediatr isn’t really comptable at all. It’s just a hidden factor Service calling back into the ioc container on each invocation… that’s easy to do on your of if that’s what you want but it has nothing to do with the events.

      @mwwhited@mwwhited2 жыл бұрын
    • @@mwwhited I think I agree with you. But also might be whether or not we are talking about "Events" or "events" (IYKWIM). My preference for "events" at the moment is MassTransit. I think an "event sourcing system"* that works by registering a series of Observable Subscriptions (or even just Observable pipelines, because then you can return something, which could be handled like a Task await on the "Other End" would be very cool). * Referring to Mediatr and MassTransit, this probably has an actual name, but I don't know it :P.

      @JonathanPeel@JonathanPeel2 жыл бұрын
    • It can also be done in C# Observable.FromEventPattern used it a few times.

      @bryanbisimotopinas345@bryanbisimotopinas345 Жыл бұрын
  • It can't get anymore simple than this. Thank you soo much howtobasic!

    @parkercrofts6210@parkercrofts6210 Жыл бұрын
  • Hey Nick, Thanks for the great content, as usual, keep up the incredible work. Would like to know your take on observables (and reactive extensions) as alternatives for events.

    @himaboy1@himaboy12 жыл бұрын
    • I am planning to make a video on ReactiveUI so yeah

      @nickchapsas@nickchapsas2 жыл бұрын
  • C# events are a language feature to support the observer design pattern. If a task at hand isn't solved by that, then don't use it.

    @evarlast@evarlast2 жыл бұрын
  • Pretty much an almost flawless approach to replacing events in modern apps. But I wanted to see what could be a flaw with this approach. The only thing I can think of that this doesn't do in a simple way is unsubscribing from the notification. Since MediatR uses DI to find the handlers, they are automatically subscribed by class signature. A way to remedy this I think is to create a optional method on a new INotificationHandler: Task ShouldSubscribeAsync(); This method is automatically called upon registration or lazily during runtime, and based on the result, either keeps or deregisters that notification handler instance for that scoped resolution of that request. Singleton would invoke this method once, transient for every request, etc. Otherwise, I feel like you have to manually deregister the dependency based on the result of the method in the early stages of the application which shouldn't have this type of logic if you are going for a clean architecture and separation of concerns. What do you guys think?

    @BlazarVision@BlazarVision2 жыл бұрын
    • It looks like there is no "dynamic" way of subscribe/unsubscribe 🤔

      @cicher@cicher2 жыл бұрын
  • Hi Nick, thanks for the cool video. One thing regarding MediatR that is doesn't support dynamic sub/unsub comparing to events or Rx. Everything that is registered in DI as an implementation of INotificationHandler will be called on mediator. Publish. Maybe workaround would be to override PublishCore base method.

    @oresthurskiy3039@oresthurskiy30392 жыл бұрын
  • I love that you're covering this.

    @CodeEvolution@CodeEvolution2 жыл бұрын
  • Really important to note here: we're talking about a captured lambda or function, not about a capturing lambda or function. Big difference. The event is capturing its handler functions, which if they capture any transient service objects, they both remain cached.

    @PaulSebastianM@PaulSebastianM2 жыл бұрын
    • Just for the sake of info completion, what is capturing a lambda or function would be like then?

      @mohamedeffat54@mohamedeffat542 жыл бұрын
    • @@mohamedeffat54 I guess he is talking about returning a delegate

      @uzayrsyed6293@uzayrsyed6293 Жыл бұрын
  • Event in C# is very powefull but alot of pple didnt know how to use it correct. Try to define the event as static and subscribe on constructor everytime. And you can use EventHandler instead of eventsarg object

    @looksharp1088@looksharp1088 Жыл бұрын
  • Really love your videos 😍 keep coding and stay safe

    @xeoneraldo1254@xeoneraldo12542 жыл бұрын
  • My issue with Mediatr notifications is that the default implementation runs all the events synchronously and if one of them throws an exception the rest fail to execute. Jimmy Bogard has documentation on how to implement a different handler. It may be worth doing a video on.

    @drewkillion2812@drewkillion28122 жыл бұрын
    • You are spoiling my videos! 😂 yes the events run sequentially (not synchronously) so what you’re saying is true. There is a way around it and there is another alternative too which I’m planning to make a video on

      @nickchapsas@nickchapsas2 жыл бұрын
    • Brighter solves this issue, I think

      @nemanjazivkovic6895@nemanjazivkovic68952 жыл бұрын
    • @@nemanjazivkovic6895 Yeah im currently using Brighter + RabbitMQ to publish and consume events out of process

      @MrBa143@MrBa1432 жыл бұрын
    • @@nemanjazivkovic6895 I wanna take a look at Brighter in a dedicated video. It has really gone under me radar

      @nickchapsas@nickchapsas2 жыл бұрын
    • Interesting..

      @Jashobantac@Jashobantac2 жыл бұрын
  • There's really no way to get around events when programming for games, where there are so many individual systems running (for instance AI/NPC) as well as player input and possibly multiplayer/server input. Also when working with speech recognizers, the recognizer isn't predictable if the speech is continuous, so events will be necessary to collect the results as they trickle in. One could set up ones own polling mechanisms but they tend to be a lot less sophisticated when created from within something like C# (i.e. no interop) than the stuff perfected by framework library creators over the course of many years. The top layer of event design should be handled by you of course, but under the hood there can be a lot of elaborate stuff going on to make events less expensive and just slicker, like hooking up to system interrupts or sniffing other events to start the polling, or up its frequency, only when logically necessary.

    @djupstaten2328@djupstaten2328 Жыл бұрын
  • Thanks for showcasing this and also showing how to properly capture Background Services with mediatr! It really depends on the use case, if you really don't need any DI or developing a lib, Events are fine imo. For bigger apps I'd definitely stick to mediatr

    @Dustyy01@Dustyy012 жыл бұрын
    • Yeah there is definitely room for them I have just found that people who don’t full understand how they work end up with not properly awaited actions and or closures that lead to bugs. The mediatr approach isn’t perfect either btw but I didn’t wanna go too deep in this video so I’ll do it in another one

      @nickchapsas@nickchapsas2 жыл бұрын
    • @@nickchapsas you mentioned async events in the Video, are you going to make a deep dive in a future video on this? What I do know is that you need to capture the delegates invocation list or to override the + and - operators to keep track of the callbacks by yourself. I dont know if there are better solutions to this but why doesn't .net bcl provide a better way? And on a sidenote, I think you made your point about the usecase for events and when not to use them👌

      @Dustyy01@Dustyy012 жыл бұрын
  • 11:09 This feels a lot like a pretty common DI issue and it's usually solved with factories. Autofac will resolve Func to a factory for transient service to allow you to do what you're talking about. Getting the ID would then look like _transientServiceFactory().Id which would create a new instance on each tick as desired.

    @oggatog3698@oggatog3698 Жыл бұрын
  • This is another one of those .... "Don't use XXX ... it causes so many problems!!!" .... where XXX can be nulls or event etc etc. I have to say I'm struggling to remember the last time I had issues using events ... in the same way I don't think I've had problems with nulls. I know I'm becoming quite an old dog now but I'd really like to stick with my events for as long as I can. Thanks for the video.

    @markharrison9021@markharrison9021 Жыл бұрын
  • May this video should have been named : "Benefits of using MEDIATR for events handling." Instead you ask a question ? I'm ok to give my opinion : With MEDIATR, it just seems that the Handlers are instanciated each time so that, their constructor param which is TransientService, will just be reinstanciated before being injected. No magic here, this is just a MEDIATR mechanism of reinstanciating handlers here. Thanks for showing this MEDIATR feature but for me this is absolutely not excluding the native events feature benefits.

    @rickyrick6901@rickyrick69018 ай бұрын
  • Thank you for great video as always. 16:18 : I expect to have the same Guid over and over because Trainsient services follow the lifetime of its injector. Since TickerService is Singleton and even not its injector (BackgroundService) is a singleton, TransientService injected into TickerService will not be disposed until TickerService is disposed. And whenever the event methods are called it will use same TransientService. And the same instance of TransientService will have the same guid which is assigned once. I personally do not see a problem with event system here. I agree that MediatR is a modern approach and very flexible. However this is a bit missleading.

    @bahtiyarozdere9303@bahtiyarozdere93032 жыл бұрын
    • The only way this would work without passing the factory of the service down would be to create a new class every time. It’s bad and I actually do events a service of not showing how bad it can really get. The feature itself isn’t bad obviously, but people (and I invite you to check on GitHub) get it more wrong than right

      @nickchapsas@nickchapsas2 жыл бұрын
    • I completly agree, if TickerService would want to new instance on every call, It would need to have a somewhat factory for TransientService, not an instance itself.

      @Lokiddr@Lokiddr2 жыл бұрын
    • Factory is definitely a shortcoming in the worker services. I have an inmplementation on stackexchange because its definitely needed.

      @T___Brown@T___Brown2 жыл бұрын
    • Can't you just workaround this by resolving the service every time with the IServiceProvider interface instead of injecting it into the singleton?. Nice video as always btw

      @yunietpiloto4425@yunietpiloto44252 жыл бұрын
    • @@yunietpiloto4425 yes but that is seen as the servicelocator anti-pattern

      @T___Brown@T___Brown2 жыл бұрын
  • I wonder what the performance difference is between mediatr and manually getting the transient service from the DI in the event

    @ironnoriboi@ironnoriboi2 жыл бұрын
  • Very cool! This gives me some ideas for useful background services

    @DummyFace123@DummyFace123 Жыл бұрын
  • Reactive Extensions offer better alternative, it even offer ability to transfom normal events to IObservable

    @fifty6737@fifty67372 жыл бұрын
    • They do but I wanna make a dedicated video on them so I had to not mention it

      @nickchapsas@nickchapsas2 жыл бұрын
    • @@nickchapsas really looking forward to Rx video!

      @chronowalker1889@chronowalker18892 жыл бұрын
  • You can also do something similar with reactive extensions

    @georgehelyar@georgehelyar2 жыл бұрын
  • You are a fantastic teacher, I'm glad I found your videos.

    @XeonProductions@XeonProductions2 ай бұрын
  • Events are a crucial part in several domains, Component based programming for example. Here is demonstrated that in a specific domain (Web handlers) they are better alternatives. Event here it is still debatable, since handlers are created and disposed for every notification. You may want this in some case, but perhaps you don't in some others

    5 ай бұрын
  • I am so glad I subbed to you. This is epic!

    @SwitchBladeGaming@SwitchBladeGaming2 жыл бұрын
  • I do like this approach better because there are other memory allocation issues if you don't set things up properly with your event subscriptions and unsubscriptions in a more traditional publisher/subscriber model.

    @TheAceInfinity@TheAceInfinity2 жыл бұрын
  • You didn't mention that `event` can be used with any delegate type. I usually just do `event Action`. I don't find the object sender to be of much use outside of specific UI frameworks.

    @protox4@protox42 жыл бұрын
    • I have a video about Func and Action coming and I mention it there

      @nickchapsas@nickchapsas2 жыл бұрын
    • Microsoft guidelines recommends using EventHandler for events. Also the reference to the sender is quite useful during debugging if your subscriber handles messages from couple producers.

      @Rizzan8@Rizzan82 жыл бұрын
  • When you are writing "Hello World", you do not really need events. You can use a mediator or not. Once you start writing something meaningful, you use something like BackgroundWorker or SerialPort or other dotnet APIs, which fire events. Once you go beyond junior level, you start working on larger projects and work with third party libraries written in other languages with COM interfaces, or do tricky stuff with operating system components. They fire C# events.

    @FromBeaverton@FromBeaverton Жыл бұрын
    • I work in larger distributed systems and MediaR is just fine for decoupling certain aspects of your business layer. No need for other 3rd party libraries or COM interfaces when a simple pub/sub model is needed.

      @jfpinero@jfpinero2 ай бұрын
  • I agree with the sentiment expressed a lot here, in the sense that I don't think you sufficiently expressed why events should be deprecated. Your original architecture is flawed, and replacing one publisher-subscribed mechanism for another observer pattern really doesn't make that much of a difference, except for the handlers apparently being newed-up on every invocation with MediatR (which I believe will be a significant expanse of your architecture design). If you truly want to get rid of events as much as possible, you should switch to Reactive Extensions, which is a proper way to handle data streams.

    @alexandermelchers1497@alexandermelchers14972 жыл бұрын
    • I could definitely have used a better original example. I will revisit that topic when I make my observers video

      @nickchapsas@nickchapsas2 жыл бұрын
  • I use events for a server side blazor session manager. It raises events to force users to log out on session expiry

    @rajm1976@rajm19762 жыл бұрын
  • This is a really good content. Thank you.

    @ThugLifeModafocah@ThugLifeModafocah Жыл бұрын
  • Amazing video as always. Just to clarify, Events/Observer and the Mediator pattern solve two different problems. In the former, you are interested in WHAT happened as well as WHO emitted that event. In the later, you are interested in WHAT happened but not always WHO emitted that event. The coupling is also different, in the Event/observer pattern, the subscriber should know the existence of the publisher, whereas in the Mediator pattern, the publisher doesn't know the existence of the subscriber and the subscriber doesn't know the existence of the publisher. Event/Observer are ideal for things like GUI or specialized services, whereas mediator is well suited for application wide communication.

    @ciberman@ciberman2 жыл бұрын
    • You shouldn't be mixing events and observer. They are different things. Events can be used to implement the observer pattern but the observer pattern doesn't need events to be implemented.

      @nickchapsas@nickchapsas2 жыл бұрын
    • @@nickchapsas Of course. I was just implying that c# events are just syntactic sugar for the ol' gang of four observer pattern.

      @ciberman@ciberman2 жыл бұрын
  • just to make sure. Does this mean that a new instance of every eventhandler (class that inherits from INotificationHandler) is created each time that event of type T happens?

    @egoegoone@egoegoone2 жыл бұрын
    • Depends on how you register mediatr

      @nickchapsas@nickchapsas2 жыл бұрын
  • So at 15:00 where you're passing in the instance of the transient service via DI... does this mean MediatR is constructing/allocating a new instance of EverySecondHandler each time that event is fired?

    @alexclark6777@alexclark67772 жыл бұрын
    • It depends on the lifetime of the handler. The default is transient yes, but you can change it.

      @nickchapsas@nickchapsas2 жыл бұрын
  • Events are not the most intuitive things to create. One thing I've sometimes used them for is cross thread communication, but in doing so you may also need to marshal to the other thread, since normally the thread that fires the event, also does the listener work.

    @jonse5a@jonse5a2 жыл бұрын
    • forgetting to unsubscribe from events can also be a source of memory leaks.

      @jonse5a@jonse5a2 жыл бұрын
  • maybe in set models for apps, where you can somewhat predict what component will be connected to another. But in Unity it's a lifesaver.

    @janjonas270@janjonas2708 ай бұрын
  • Hi, Nick! At 4:47 i see autocorrection "handELR" -> "handLER". What plagin You use for that?

    @yummybunny7351@yummybunny73512 жыл бұрын
    • Video editing 😂

      @nickchapsas@nickchapsas2 жыл бұрын
  • Did you ever use ReactiveExtensions an if so, do you have an opinion on it?

    @hichaeretaqua@hichaeretaqua Жыл бұрын
  • Hey Nick, I'm a bit confused about the GUID issue. If you're requesting transient services from the BackgroundService shouldn't you inject the ServiceProvider and then get a new scope and resolve services every tick? Wouldn't that give a new GUID?

    @kevinlloyd9507@kevinlloyd95072 жыл бұрын
    • Injecting the ServiceProvider is an anti pattern called service locator. It should be avoided because you never know what services will be resolved if you do that

      @nickchapsas@nickchapsas2 жыл бұрын
    • @@nickchapsas MediatR is really just a wrapper around a service locator. If you are using Microsoft DI it is the service provider that it is calling in the end is it not?

      @RENAUDADAM@RENAUDADAM2 жыл бұрын
    • @@RENAUDADAM service locator pattern is an anti pattern which should be avoided in most use cases, but if you are building frameworks (such as mediator) then it can be okay, but using it as a normal way of pulling "magic" dependencies out of thin air into a class should be avoided, it makes your code hard to test. It goes against the dependency inversion principal.

      @shakeuk@shakeuk2 жыл бұрын
    • @@RENAUDADAM sure but it’s not MY service locator. I don’t know about any of it and nothing in my application knows about it either. There is a big difference there. Dictionary.ContainsKey uses gotos. That doesn’t mean that I would use gotos

      @nickchapsas@nickchapsas2 жыл бұрын
    • @@nickchapsas great video man! I have a question, sorry i don't have much experience. If i want a new viewmodel for example so it has to be "empty" or as its initial state, how do i get one without saying new() or the service provider? For example the user switches between some views and everytime they have to be resetted..

      @andreamariotto348@andreamariotto3482 жыл бұрын
  • Like the video, but a question: In the handlers, why did you do the pattern Console.WriteLine(...); return Task.Completed... instead of await Console.Out.WriteLineAsync(...); ?

    @JacobSmith-hj2kt@JacobSmith-hj2kt2 жыл бұрын
  • Despite the fact that I was aware of the existence of the `event` keyword in C# due to my experiments in the Unity game engine, my webdev job always just creates an interface with some async handler methods, a manager that loads services implementing the interface via DI, and then executes all of the async methods before or after whatever operations it performs. Now I wonder what value there might be in refactoring such things into `event` instances and the subscriptions to them. Thoughts?

    @MrEnvisioner@MrEnvisioner2 жыл бұрын
  • thanks master, but we can use new guid before publish? its same right? and use transient services

    @SirPrsty@SirPrsty2 жыл бұрын
  • When you’re using the built in events. The handler is listening for events from a specific instance. How would you accomplish the same thing using mediatr eventhandlers? For example if you have two instances of TickerBackgroundService running but you only want events from one of them?

    @Fuel16vt@Fuel16vt Жыл бұрын
  • 0:15 great transition, at first I didn't even notice it.

    @lukkkasz323@lukkkasz323 Жыл бұрын
  • Thanks for the great video. If I have a worker as a hosted service. This then fetches new orders every second as an example. This is done in a separate class where a HttpClient is needed. (Injected in the class which inhetit from BackgroundService) How does it make sense to use these mediator notifications? Are there other advantages than "only" the handling of the lifecycles? Greetings from Switzerland

    @maurohefti1157@maurohefti11572 жыл бұрын
    • Another approach could be to get an instance of the separate class via an injected ServiceProvider (core's IOC container). As a result the lifetime of the separate class (and its dependencies) is observed.

      @ryan-heath@ryan-heath2 жыл бұрын
    • @@ryan-heath Thx for yout answer. Yes, that's right. But for me, the lifetime doesn't really matter. Should you still prefer the notification pattern? For out use case ServiceProvider often is an anti pattern.

      @maurohefti1157@maurohefti11572 жыл бұрын
    • @@maurohefti1157 for a singleton background service I don’t think service provider is an anti pattern, but in general it is an anti pattern, yes. Would I use a notification service for something that runs every few seconds? No. We have timers for that. Your service fetches for new orders. If there was a “new order arrived” event, then subscribing to such event would make more sense than pooling each few seconds for new orders.

      @ryan-heath@ryan-heath2 жыл бұрын
  • Nick you such a legend bro, I learn so much from you, keep it up!

    @RoughSubset@RoughSubset2 жыл бұрын
  • 11:59 Unrelated, but I was curious about why I often see types being passed into methods to mark an Assembly for scanning? Why not pass in the actual Assembly object, possibly obtained from Assembly.GetExecutingAssembly() ? Or is is purely for consistency, if the Assembly you want to refer to is not the current executing assembly, so instead you pass in a type from the aseembly you intended to target?

    @Gruggo@Gruggo2 жыл бұрын
    • It’s for deterministic execution. Code can be moved around, the project might be referenced by another project etc

      @nickchapsas@nickchapsas2 жыл бұрын
  • Message busses like RabbitMQ uses traditional events (which I agree on, it's not very elegant). Is there any way to use an implementation like Mediator for that? I see many people using traditional event handlers for Async messaging in micro service architecture.

    @Krilllind@Krilllind2 жыл бұрын
    • Maybe building a wrapper for each event? Of course you still need to subscribe to an event, but you wouldn't have the scoping problem.

      @jasdefer@jasdefer2 жыл бұрын
  • Good post. Thank you.

    @kevinmerrell9952@kevinmerrell99522 жыл бұрын
  • Hey Nick can you publish video of mostly used design patterns in c# and how ? And when to used it.

    @ADSNGreenLife@ADSNGreenLife2 жыл бұрын
  • I use IServiceScopeFactory when I need to consume transient or scoped in a singleton

    @f135ta@f135ta7 ай бұрын
  • I think you have omitted biggest advantage of mediatr approach - handler does not have know anything about publisher so things are nicely decoupled. But there are completely valid use cases for events in backend applications too - for example I don't think that you would want to inject mediatr to some domain/utility class like processing progress tracker.

    @radol@radol2 жыл бұрын
  • This was finally the mediator video that clicked for me

    @DoorThief@DoorThief2 жыл бұрын
  • i feel that use mediatr or events is almost the same 99% of time, i use events a lot because is do a lot of desktop apps and i think they are actually comfy to use, but still nice to see other ways to do the same.

    @anonimxwz@anonimxwz9 ай бұрын
  • But Nick one of your video you said MediatoR will take more memory and will it be fit for every time, like a silver bullet?

    @Rajeshsingh-ws5th@Rajeshsingh-ws5th2 жыл бұрын
    • I dont think that the memory allocated here is prohibitive. If you need the most efficient version possible you can totally build something custom or use events but you have to be extremely careful because they can lead to bad performance too

      @nickchapsas@nickchapsas2 жыл бұрын
  • exceptional video ty

    @TheCMajor9th@TheCMajor9th2 жыл бұрын
  • Could you use record types to simplify those arg classes with constructor injection and a getter?

    @lukassinkus6162@lukassinkus61622 жыл бұрын
    • No because they need to extend EventArgs and it kinda defeats the purpose of the record. If you do manual eventing then yeah you can

      @nickchapsas@nickchapsas2 жыл бұрын
    • @@nickchapsas actually,you don't have to subclass eventargs. EventHandler is just a convention and nothing more than an Action. Just create an event with an Action based delegate and everything is dandy. This also allows for async events, by using Func though the invocation of those is harder, since you have to get the multicast delegates invocation list and cast them to the respective Func to await the calls properly... I'd never think of providing a library that is strictly coupled to mediator or another library to provide events to an application.

      @Kirides@Kirides2 жыл бұрын
  • Be hard for someone like myself to move away from built in events and delegates just to gain pub sub observer. Unless there is specific cases where it falls short which is what you've highlighted. But still it'd be more a case of using the package/approach for the exception rather than abandoning events altogether. Usually it's a matter of objects passing data and context without them having to know about each other. I'm glad it's a built in feature

    @fabianmitchell9443@fabianmitchell94432 жыл бұрын
    • They actually have to know about each others with events…

      @maurosampietro9900@maurosampietro9900 Жыл бұрын
  • Implementing async events really isn’t that much work, you can just use delegates and task with event handlers and it ends up working quite nicely, I’m surprised there isn’t for support/documentation on async events as in certain use case there very powerful

    @justgame5508@justgame55082 жыл бұрын
  • In this case would be similar to have Masstransit in place instead of MediaR, I will have more benefits (persistence, queuing) what is your opinion?

    @MrIsrael3000@MrIsrael3000 Жыл бұрын
    • Sometimes you don't need persistence and/or queuing. You just want to decouple some action from running in the same namespace for example.

      @jfpinero@jfpinero2 ай бұрын
  • I was half expecting you to show an approach with lambdas. So MediatR is scanning your assembly for INotificationHandler's? It seems like trouble to create classes containing only 1 constructor and 1 function, to avoid capturing by lambda. Maybe it's the popular Dependency Injection pattern that's bothering me (not sure). My gut feeling is that i would want to reduce the amount of code. Could you avoid capturing values by using a static method as a handler? (a static lambda?)

    @xybersurfer@xybersurfer2 жыл бұрын
    • You can but at that point, why? You’re just trying to latch a “flawed” design approach. Not that creating a new class per processing is better but it’s less likely to cause behavioural problem

      @nickchapsas@nickchapsas2 жыл бұрын
    • ​@@nickchapsas it is indeed not a proper fix to a flawed design and yes i completely agree with that, with the current state of the c# (i still prefer the language over most others). i personally would like to have "everything" compile-time checked. it's something i have been missing with Dependency Injection. i feel that c# has been moving more towards run-time checks unfortunately

      @xybersurfer@xybersurfer2 жыл бұрын
  • What about performance? Does MediatR delivery the same performance as old fashioned events?

    @jorgerochagualtieri@jorgerochagualtieri2 жыл бұрын
  • I dont often comment on youtube. But dang as a senior engineer working for microsoft. This stuff is really good .

    @sethreidnz1@sethreidnz12 жыл бұрын
  • This is a clever alternative but what is the performance difference for expensive event handlers. It seems that Mediator would create and destroy the objects for every call.

    @Eric-kx7do@Eric-kx7do2 жыл бұрын
    • But that’s fine because you want proper scoping. The risk of closure in the event handler approach is way more dangerous because it won’t be just slow it will also capture dependencies and cause bugs

      @nickchapsas@nickchapsas2 жыл бұрын
    • People are often worried about DI having to have to create many objects and that being slow or taking too much memory. In reality, if you for example have a C# class with some logic and say 4 dependencies (some injected services), the resulting piece of memory allocated for that object is really just 4 pointers to the dependencies. Now compare that to a foreach that creates an iterator and causes about the same. But somehow people don't think about that.

      2 жыл бұрын
    • @ If it's transient then it's constantly reallocating those 4 dependencies, if it's an iterator then it's just allocated once.

      @ShadoFXPerino@ShadoFXPerino2 жыл бұрын
    • ​@@ShadoFXPerino yes but the point I am trying to make is that people are not rational in this regard and somehow fear this one allocation of the transient object. The same people then go on and create a monster Linq in some hot spot method of some Singleton. In my opinion it is a good price to pay for having the scoping clearly handled.

      2 жыл бұрын
    • @ You are very correct on that irrational obsession, and I'll admit, I have probably obsessed just like that on more than one occasion. However, I think the impact this could have on the garbage collector when you subscribe with many handlers can be a valid concern. Of course, then your main problem is just that you think you have too many handlers, but if you subscribe with stateless objects, like most services, then you can argue that this is waste... Though I wonder, if there is an "INotificationHandler" interface, then maybe there also exists something like an "INotificationStateless" interface from which objects would be put in a singleton.

      @flyingmadpakke@flyingmadpakke2 жыл бұрын
  • One thing Visual Studio has over Rider is that to looks better in video regardless of the theme selected.

    @johnolawale2749@johnolawale27492 жыл бұрын
  • Mediatr is really good when used with behaviours they are like a middlewares for your notifications and publishing

    @cnikolov@cnikolov2 жыл бұрын
  • Nice alternative to classic events management inside an api managing server. Really good job and keep up!🎉

    @HaythemKaroui@HaythemKaroui Жыл бұрын
  • This is neat! Thanks!

    @Sad-Lemon@Sad-Lemon2 жыл бұрын
  • It's like an event aggregator. I thought everyone knew about this. I had an interview yesterday for a xamarin role and I was asked how to talk from platform to forms and my first instinct was an event aggregator. I thought that was just how IoC works. I've never used it on the backend, but I can see many use cases (like the simple example here). The problem with the GUID could be solved with: public Guid Id => Guid.NewGuid(); I still like the solution you provided though.

    @pqsk@pqsk Жыл бұрын
    • The Guid issue could be solved like that but it's bad practice and makes unit testing difficult. Hence just like DateTime.Now it should be put behind an interface/class and injected into other classes that need it via IoC. In the real world you might do it if you're being lazy but don't do it in an interview and be able explain why you should not do it.

      @dwhxyz@dwhxyz Жыл бұрын
    • @@dwhxyz to clarify, I wasn't implying that that was the ultimate solution. When we program (especially in deadlines) sometimes we need a quick solution that works. That's merely what I was suggesting. Of course it's bad to not have a piece of code testable.

      @pqsk@pqsk Жыл бұрын
  • What a coincidence! I've recently had this thought as to why the classic event based approach isn't as prevalent in apps nowadays. In reality, we've just moved to a more message bus based pub-sub model, such as MediatR. By the way, I was unaware of MediatR having a notification based model. Thank you for sharing! I was planning on going with something like RabbitMQ for a personal project but actually MediatR notifications are perfect.

    @ColinM9991@ColinM99912 жыл бұрын
  • Danke!

    @TurboTheo13@TurboTheo13 Жыл бұрын
  • Thank you Nick this tutorial it was very helpfullllllllllll!!!!!!

    @kwstaslalaounis3212@kwstaslalaounis32122 жыл бұрын
  • I completely agree with your reasoning and your suggestion of an alternative solution. Classical events are for WinForms/WPF and that's it.

    @krccmsitp2884@krccmsitp28842 жыл бұрын
  • I think this is interesting. I don't know that it completely makes events irrelevant to me but it seems like a nice pattern to reach for when you know there's going to be many consumers. You can avoid using labels/goto if people get upset by using while(true){} . It does make me a little sad how much indirection is required or at least normal convention in C#. I wonder how much of the unit testing is actually useful and productive in a typesafe language, and how we probably could be putting more constraint in our constructors/properties to lose the need for several unit tests. I'm not advising anyone actually do that as a general philosophy, because I think that's a terrible idea at face value, but I do think that maybe someone should be exploring the idea. Can you just defend the boundaries of the object and obviate classes of unit test.

    @ARVash@ARVash2 жыл бұрын
  • Interesting, because I am now using it a lot with Blazor.

    @rirajojo@rirajojo Жыл бұрын
  • Looks like something from Java to me. You have an observer/listener pattern with a mediator. I think it's good for application or system wide events as it only adds dependencies to the mediator. But for local messages C# events are better. A lot less code and slightly better performance.

    @CockroachSlidy@CockroachSlidy2 жыл бұрын
    • You’re mixing observer and mediator. They are completely different things. There will be an observer video coming soon

      @nickchapsas@nickchapsas2 жыл бұрын
    • @@nickchapsas Notification listeners are observers in your example.

      @CockroachSlidy@CockroachSlidy2 жыл бұрын
    • @@CockroachSlidy No they are not. They aren't observing anything. They are notification handlers but they don't listen to anything.

      @nickchapsas@nickchapsas2 жыл бұрын
  • Can we talk now about Event Sourcing in Event Driven Architecture? :D Thanks for highly informative video as always!

    @emoney9979@emoney99792 жыл бұрын
    • Yes this would be interesting

      @megaman2016@megaman20162 жыл бұрын
    • There is a video I’m really proud of about event sourcing coming

      @nickchapsas@nickchapsas2 жыл бұрын
  • Nick Why not replace C# event with Reactive Extensions? Need to know your opinion about it

    @mehdisalehi@mehdisalehi2 жыл бұрын
  • Awesome! Thank you :-)

    @stef2528@stef2528 Жыл бұрын
  • Awesome video as always. What tool do you use to show that red rectangle so quickly (at 2.30 in the video)?

    @FlavienDeslandres@FlavienDeslandres Жыл бұрын
  • Interesting extension. Did not know so far

    @patrickrainer2507@patrickrainer25072 жыл бұрын
  • I was actually curious that with the goto code it doesnt spam the console resp. onbuttonpressed event with null or string empty :)

    @Alex-gj2uz@Alex-gj2uz2 жыл бұрын
    • The Console.ReadKey() method will wait for a key to be pressed before continuing.

      @gnack420@gnack420 Жыл бұрын
  • Sry, for this maybe "stupid" question, but if you attach the eventHandler in the constructor then how you detach the eventHandler, if the object is destroyed? Do you have to overwrite the destruct constructor (~TickerService)? Or what will be best solution?

    @devchannel5232@devchannel52322 жыл бұрын
    • no need, since when tickerservice is collected also its methods are collected. you do need to be wary of events and eventhandlers though, in other cases you could cause a memory leak

      @TheToeb@TheToeb2 жыл бұрын
    • @@TheToeb Memory leak is what i thought. So the gc will take care of this case...thanks!

      @devchannel5232@devchannel52322 жыл бұрын
    • Not really a stupid question at all, and hits at the root of the problem. The difference between the two models is who 'owns' what. In the older event model the event handler is responsible for doing the work. The event pulls in the objects it needs, and then does the work. The object itself has no idea what might happen to it, which can be a problem if that object might want to do something that those closures need to know about (such as being disposed of, or switched out). In the publishing model data is pushed to objects, and the event has no idea what might be done with that data. The major difference is that the object definitely knows about event handler, and so can definitely send messages back to it. 2 way communication is possible, and basic functionality can be available by default (such as dependency injection, or disposal). Unfortunately there is no general answer to what an event closure should do in the case of disposal of one of it's dependencies, but defaulting to disposing itself (and informing it's other dependencies it has done so) seems reasonable. It is inherently a 2 way communication problem. Standard events are a lightweight solution where we know that one way communication is sufficient, but for anything above the lowest levels it usually isn't. How you extend it to a 2 way system is a more complicated problem, and I'm not qualified to post an opinion on what the 'best' way is. My first thought would be that you would definitely want to be wrapping it rather than using events directly though. Whatever you do will come with some overhead, which is why we still want the normal event system.

      @agsystems8220@agsystems82202 жыл бұрын
    • @@agsystems8220 Just as an aside I tend to go away from events other than when it is necessary to interact with third party libraries. Instead I use System.Reactive / IObservable/ IObserver because it allows more control over subscription and disposal as well as bringing in alot of functionality (reactive.linq) also it might be more lightweight than a larger system such as mediatr (though i haven't measured it)

      @TheToeb@TheToeb2 жыл бұрын
  • You Go FAST But You're Great!

    @AlfredoLopez-mc8ds@AlfredoLopez-mc8ds2 жыл бұрын
  • Hi Nick, Thanks for sharing this video with us. It's awesome. I did not know about this lib. For more complex scenarios I was using most of the times Akka.Net. But for all in process communications this lib is perfect. Could you also please share your sample code with us?

    @christianstadler6575@christianstadler65752 жыл бұрын
    • That is the standard code for mediaR. But seriouly akka is a nightmare for big projects; I am working in one. I wonder why we can’t have a simpler approach like this one or other pub/sub approaches while handling some situations like this. This would made life easier for the people who would be working on the projects javing akka in backend… Btw you can simply search for mediatR examples for .net core.

      @sidmendax@sidmendax2 жыл бұрын
  • Awesome video as usual

    @zedzulzur@zedzulzur2 жыл бұрын
  • wow. fantastic content.

    @ericvosselmans5657@ericvosselmans56572 жыл бұрын
  • How do I run this Api in Visual Studio 2022 ver 17.8.6 and see a Console output? Using minimal APi with no swagger, auth or https. Only options i see is http, IIS Express and WSL...

    @Memento2747@Memento27472 ай бұрын
  • This is great. Now I don't have to regret never getting my head around events.

    @lexxynubbers@lexxynubbers Жыл бұрын
  • Can you make a video about NativeAOT?

    2 жыл бұрын
  • Man, Nick great video again.

    @josephizang6187@josephizang61872 жыл бұрын
  • This is called weak event pattern and has been around since. NET 1.1 days. There are various forms of it, with varying benefits. But I agree I like it more than events which are bit more cumbersome.

    @NawfalHasan@NawfalHasan2 жыл бұрын
  • For me it's a design problem but anyway c# isn't just for apps back, events and observable pattern is still relevant for video games

    @AkioJunichiro@AkioJunichiro2 жыл бұрын
  • I got an application in blazor build around events. Events only make sense around state. Since backend is 90% statelless then you may never need events.

    @FarukAFeres@FarukAFeres7 ай бұрын
KZhead