Are events in C# even relevant anymore?

Поделиться
HTML-код
  • Опубликовано: 23 ноя 2024

Комментарии • 392

  • @nickchapsas
    @nickchapsas  2 года назад +81

    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.

    • @adambickford8720
      @adambickford8720 2 года назад +2

      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()

    • @frotes
      @frotes 2 года назад +1

      Can’t wait for RX! After using RSJX, wanted to give it a shot in NET too

    • @teodorchirileanu
      @teodorchirileanu 2 года назад

      Please notify me!

    • @frotes
      @frotes 2 года назад +1

      Hope this one is still upcoming!

    • @austinescobedo5006
      @austinescobedo5006 2 года назад +1

      @@frotes I second this!

  • @ryanlashkevich9615
    @ryanlashkevich9615 2 года назад +68

    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.

    • @nickchapsas
      @nickchapsas  2 года назад +6

      Events, the observer pattern and the mediator pattern are all separate things

    • @ryanlashkevich9615
      @ryanlashkevich9615 2 года назад +34

      Events is a built-in observer pattern. Similar to IEnumerable (Iterator pattern, but implemented, actually better than officially described by GoF). My imho.

    • @wobuntu
      @wobuntu 2 года назад +25

      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

    • @jonathandunn9302
      @jonathandunn9302 2 года назад +3

      @@wobuntu Agreed! Maybe I'm just bad at C# but for my front-end use cases in Unity Actions and Events do just fine.

    • @gnack420
      @gnack420 2 года назад +5

      @@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.

  • @Haapavuo
    @Haapavuo 2 года назад +175

    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.

    • @Wobling
      @Wobling 2 года назад +36

      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.

    • @dahliaspumpski5837
      @dahliaspumpski5837 2 года назад +4

      As someone who will be starting to use unity soon I appreciate these comments!

    • @Artmos
      @Artmos 2 года назад +3

      I am going to second Atoms for Unity and would even suggest combining it with Reactive programming using UniRx

    • @Haapavuo
      @Haapavuo 2 года назад +9

      @@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.

    • @Artmos
      @Artmos 2 года назад +1

      @@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.

  • @looksharp1088
    @looksharp1088 Год назад +2

    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

  • @markharrison9021
    @markharrison9021 2 года назад +5

    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.

  • @BlazarVision
    @BlazarVision 2 года назад +7

    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?

    • @cicher
      @cicher 2 года назад

      It looks like there is no "dynamic" way of subscribe/unsubscribe 🤔

  • @protox4
    @protox4 2 года назад +5

    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.

    • @nickchapsas
      @nickchapsas  2 года назад +6

      I have a video about Func and Action coming and I mention it there

    • @Rizzan8
      @Rizzan8 2 года назад +1

      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.

  • @drewkillion2812
    @drewkillion2812 2 года назад +17

    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.

    • @nickchapsas
      @nickchapsas  2 года назад +34

      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

    • @nemanjazivkovic6895
      @nemanjazivkovic6895 2 года назад +3

      Brighter solves this issue, I think

    • @MrBa143
      @MrBa143 2 года назад +1

      @@nemanjazivkovic6895 Yeah im currently using Brighter + RabbitMQ to publish and consume events out of process

    • @nickchapsas
      @nickchapsas  2 года назад +8

      @@nemanjazivkovic6895 I wanna take a look at Brighter in a dedicated video. It has really gone under me radar

    • @Jashobantac
      @Jashobantac 2 года назад

      Interesting..

  • @myuuiii
    @myuuiii 2 года назад +56

    That blur at the start 😂 I’m curious

    • @nickchapsas
      @nickchapsas  2 года назад +37

      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

    • @Gruggo
      @Gruggo 2 года назад +10

      Makes sense, I was thinking "What kind of insidious nonsense are we writing to the console?"

  • @oggatog3698
    @oggatog3698 Год назад +11

    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.

  • @fifty6737
    @fifty6737 2 года назад

    Reactive Extensions offer better alternative, it even offer ability to transfom normal events to IObservable

    • @nickchapsas
      @nickchapsas  2 года назад +2

      They do but I wanna make a dedicated video on them so I had to not mention it

    • @chronowalker1889
      @chronowalker1889 2 года назад

      @@nickchapsas really looking forward to Rx video!

  • @PaulSebastianM
    @PaulSebastianM 2 года назад +10

    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.

    • @mohamedeffat54
      @mohamedeffat54 2 года назад +1

      Just for the sake of info completion, what is capturing a lambda or function would be like then?

    • @uzayrsyed6293
      @uzayrsyed6293 Год назад

      @@mohamedeffat54 I guess he is talking about returning a delegate

  • @djupstaten2328
    @djupstaten2328 Год назад +3

    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.

  • @JonathanPeel
    @JonathanPeel 2 года назад +13

    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.

    • @mwwhited
      @mwwhited 2 года назад

      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.

    • @JonathanPeel
      @JonathanPeel 2 года назад

      @@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.

    • @bryanbisimotopinas345
      @bryanbisimotopinas345 2 года назад

      It can also be done in C# Observable.FromEventPattern used it a few times.

  • @BeyondAppearances-0
    @BeyondAppearances-0 Год назад +1

    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.

  •  11 месяцев назад +1

    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

  • @FromBeaverton
    @FromBeaverton 2 года назад +3

    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.

    • @jfpinero
      @jfpinero 8 месяцев назад

      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.

  • @bahtiyarozdere9303
    @bahtiyarozdere9303 2 года назад +10

    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.

    • @nickchapsas
      @nickchapsas  2 года назад +1

      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

    • @Lokiddr
      @Lokiddr 2 года назад +1

      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.

    • @T___Brown
      @T___Brown 2 года назад

      Factory is definitely a shortcoming in the worker services. I have an inmplementation on stackexchange because its definitely needed.

    • @yunietpiloto4425
      @yunietpiloto4425 2 года назад

      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

    • @T___Brown
      @T___Brown 2 года назад

      @@yunietpiloto4425 yes but that is seen as the servicelocator anti-pattern

  • @evarlast
    @evarlast 2 года назад +11

    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.

    • @fronkh
      @fronkh 3 месяца назад

      or the mediator pattern. I love that one

  • @alexandermelchers1497
    @alexandermelchers1497 2 года назад +1

    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.

    • @nickchapsas
      @nickchapsas  2 года назад +2

      I could definitely have used a better original example. I will revisit that topic when I make my observers video

  • @jonse5a
    @jonse5a 2 года назад +1

    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
      @jonse5a 2 года назад +1

      forgetting to unsubscribe from events can also be a source of memory leaks.

  • @Eric-kx7do
    @Eric-kx7do 2 года назад +12

    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.

    • @nickchapsas
      @nickchapsas  2 года назад +11

      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

    •  2 года назад +3

      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.

    • @ShadoFXPerino
      @ShadoFXPerino 2 года назад

      @ If it's transient then it's constantly reallocating those 4 dependencies, if it's an iterator then it's just allocated once.

    •  2 года назад +1

      ​@@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.

    • @flyingmadpakke
      @flyingmadpakke 2 года назад +1

      @ 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.

  • @DoorThief
    @DoorThief 2 года назад +2

    This was finally the mediator video that clicked for me

  • @ciberman
    @ciberman 2 года назад +6

    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.

    • @nickchapsas
      @nickchapsas  2 года назад +2

      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.

    • @ciberman
      @ciberman 2 года назад +1

      @@nickchapsas Of course. I was just implying that c# events are just syntactic sugar for the ol' gang of four observer pattern.

  •  8 дней назад

    An IDisposable object that exposes events should always assign null to the events on disposal to prevent memory leaks. UI programming would be very difficult without events.

  • @LynxxLancer
    @LynxxLancer 2 года назад +1

    This is just an EventAggregator, which have existed for a long time. If you're writing WPF apps, then this stuff is no brainer though I still prefer events because it is much cleaner and I will always know the source of the event.

  • @justgame5508
    @justgame5508 2 года назад +4

    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

  • @logank.70
    @logank.70 2 года назад +3

    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.

  • @TheAceInfinity
    @TheAceInfinity 2 года назад

    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.

  • @R.Daneel
    @R.Daneel 2 года назад +1

    Good timing. I happen to be dealing with this exact thing right now. Thanks!

  • @mojizze
    @mojizze 2 года назад +1

    One thing Visual Studio has over Rider is that to looks better in video regardless of the theme selected.

  • @21yarpen
    @21yarpen 2 года назад +2

    Sorry, not convinced at all.
    Your expected result which I would sum up as:
    1. Handler of event without "memory", new instance every time.
    2. async calling.
    It's not "default" setting for events, but still it's very easy to make them work that way. With simpler code in which you see the behavior. If I see code, which looks like some plain old class with injected dependensy to some service, and for some strange reason this class is instanced every time, I woud not call this code good.
    You could get the same result with just simple factory or get returning new instance change. Like one line of code and you know -> Ok, I will get new guid every time I use it.
    As for the async you have full control with events over how and when event would fire. You can filter subs, you can fire them sync, you can use tasks, queues and bilion other things with that. async handler isn't always a way do it.
    To sum up, question.
    Let change your example. I want it to write those guids on some file -> poor man simplest log.

  • @ironnoriboi
    @ironnoriboi 2 года назад +4

    I wonder what the performance difference is between mediatr and manually getting the transient service from the DI in the event

  • @egoegoone
    @egoegoone 2 года назад +1

    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?

    • @nickchapsas
      @nickchapsas  2 года назад +2

      Depends on how you register mediatr

  • @georgehelyar
    @georgehelyar 2 года назад +4

    You can also do something similar with reactive extensions

  • @lukkkasz323
    @lukkkasz323 2 года назад

    0:15 great transition, at first I didn't even notice it.

  • @parkercrofts6210
    @parkercrofts6210 2 года назад

    It can't get anymore simple than this. Thank you soo much howtobasic!

  • @janjonas270
    @janjonas270 Год назад

    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.

  • @XeonProductions
    @XeonProductions 8 месяцев назад

    You are a fantastic teacher, I'm glad I found your videos.

  • @oresthurskiy3039
    @oresthurskiy3039 2 года назад +4

    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.

  • @sethreidnz1
    @sethreidnz1 2 года назад +1

    I dont often comment on youtube. But dang as a senior engineer working for microsoft. This stuff is really good .

  • @FarukAFeres
    @FarukAFeres Год назад

    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.

  • @ADSNGreenLife
    @ADSNGreenLife 2 года назад +1

    Hey Nick can you publish video of mostly used design patterns in c# and how ? And when to used it.

  • @kevinlloyd9507
    @kevinlloyd9507 2 года назад +9

    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?

    • @nickchapsas
      @nickchapsas  2 года назад +9

      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

    • @RENAUDADAM
      @RENAUDADAM 2 года назад +1

      @@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?

    • @shakeuk
      @shakeuk 2 года назад +1

      @@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.

    • @nickchapsas
      @nickchapsas  2 года назад +3

      @@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

    • @andreamariotto348
      @andreamariotto348 2 года назад

      @@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..

  • @anonimzwx
    @anonimzwx Год назад

    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.

  • @rickvelde7967
    @rickvelde7967 2 года назад +3

    The thing I hate about events in C# is that they don't really conform to other rules of the language which restricts your ability to do simple metaprogramming and makes falling back to reflection extra confusing. I think I am even more scared of an ecosystem where there are competing strategies for handling events which will likely end up smashed together in larger projects. I think that the design of events needs to be revisited so that a backwards compatible solution can be created to make events more extensible so they can be adapted to handle more use cases.

    • @ernstraedecker6174
      @ernstraedecker6174 2 года назад +6

      A C# event handler is just a delegate with extra frills, allowing you to use += and -= to attach it to an even variable (like Button.Click). And a delegate is just a clunky behind the scenes class for a function pointer.
      Events should ALWAYS be synchronous, because they should notify you NOW about what is happening NOW. The whole example of having an asynchronous event notification is horrible.

  • @radol
    @radol 2 года назад

    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.

  • @rajm1976
    @rajm1976 2 года назад

    I use events for a server side blazor session manager. It raises events to force users to log out on session expiry

  • @CodeEvolution
    @CodeEvolution 2 года назад

    I love that you're covering this.

  • @CockroachSlidy
    @CockroachSlidy 2 года назад +1

    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.

    • @nickchapsas
      @nickchapsas  2 года назад

      You’re mixing observer and mediator. They are completely different things. There will be an observer video coming soon

    • @CockroachSlidy
      @CockroachSlidy 2 года назад

      @@nickchapsas Notification listeners are observers in your example.

    • @nickchapsas
      @nickchapsas  2 года назад

      @@CockroachSlidy No they are not. They aren't observing anything. They are notification handlers but they don't listen to anything.

  • @DummyFace123
    @DummyFace123 Год назад

    Very cool! This gives me some ideas for useful background services

  • @AlfredoLopez-mc8ds
    @AlfredoLopez-mc8ds 2 года назад +1

    You Go FAST But You're Great!

  • @rirajojo
    @rirajojo Год назад

    Interesting, because I am now using it a lot with Blazor.

  • @bogdanbanciu1781
    @bogdanbanciu1781 2 года назад +2

    The dance while pressing buttons killed me ahaha

  • @80-two
    @80-two Год назад

    I use IServiceScopeFactory when I need to consume transient or scoped in a singleton

  • @hichaeretaqua
    @hichaeretaqua Год назад +1

    Did you ever use ReactiveExtensions an if so, do you have an opinion on it?

  • @lawrencejob
    @lawrencejob 2 года назад

    Mediatr vs Events are drastically different in implementation and architecture pattern and arguably Mediatr is more frowned upon than events!
    Mediatr is about messaging at the business level, where events are about control flow at the application level

    • @nickchapsas
      @nickchapsas  2 года назад

      There is nothing business specific for MediatR. It was not made for that and it was not build around that idea.

  • @Fuel16vt
    @Fuel16vt Год назад

    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?

  • @AkioJunichiro
    @AkioJunichiro 2 года назад +3

    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

  • @ShadoFXPerino
    @ShadoFXPerino 2 года назад +3

    Object modularity vs dependency injection. If you'd have went back to Y2K and told them you're going to reinstantiate every object for every tick they'd call you a nutjob. Then we had global internet, gigs of ram, stagnating CPU clock rates, and 32-core CPUs and it didn't sound so stupid anymore.

  • @patrickrainer2507
    @patrickrainer2507 2 года назад

    Interesting extension. Did not know so far

  • @Dustyy01
    @Dustyy01 2 года назад

    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

    • @nickchapsas
      @nickchapsas  2 года назад +1

      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

    • @Dustyy01
      @Dustyy01 2 года назад

      @@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👌

  • @pqsk
    @pqsk 2 года назад

    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.

    • @dwhxyz
      @dwhxyz Год назад

      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.

    • @pqsk
      @pqsk Год назад +1

      @@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.

  • @cnikolov
    @cnikolov 2 года назад

    I wouldn't say its dead node js is progressing a alot on events, also if you don want to use packages you could use the observer pattern.

    • @nickchapsas
      @nickchapsas  2 года назад +1

      Absolutely. This video isn’t about the concept of events but about the event keyword and mechanism

  • @7th_CAV_Trooper
    @7th_CAV_Trooper 2 года назад

    Events are relevant. It's how the IObservable stuff works and it's how you notify other classes of state changes in any UI context.
    IMediator is cool if you're not doing UI work. There's also TPL.

    • @nickchapsas
      @nickchapsas  2 года назад

      Observable works with callbacks not events

    • @7th_CAV_Trooper
      @7th_CAV_Trooper 2 года назад

      Yeah, that's what I get for commenting on something I haven't touched for 5 years. INotifyPropertyChanged does indeed use callbacks. But the UI is still driven by events.

    • @7th_CAV_Trooper
      @7th_CAV_Trooper 2 года назад

      @@nickchapsas Do you think IMediator replaces TPL?

    • @nickchapsas
      @nickchapsas  2 года назад +1

      @@7th_CAV_Trooper I think you misunderstood me. I think that the event keyword and that event mechanism is irrelevant. Not events/callbacks or delegates as a concept. Just that specific implementation of the event feature. MAUI, Blazor etc can still use events internally but you only interact with the implementation of those events, not with the event itself.

    • @7th_CAV_Trooper
      @7th_CAV_Trooper 2 года назад

      @@nickchapsas yeah, I'm with you now. btw, love your channel and share your videos often.

  • @fabianmitchell9443
    @fabianmitchell9443 2 года назад

    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

    • @maurosampietro9900
      @maurosampietro9900 2 года назад

      They actually have to know about each others with events…

  • @cnikolov
    @cnikolov 2 года назад

    Mediatr is really good when used with behaviours they are like a middlewares for your notifications and publishing

  • @NawfalHasan
    @NawfalHasan 2 года назад

    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.

  • @himaboy1
    @himaboy1 2 года назад +14

    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.

    • @nickchapsas
      @nickchapsas  2 года назад +16

      I am planning to make a video on ReactiveUI so yeah

  • @alexclark6777
    @alexclark6777 2 года назад +1

    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?

    • @nickchapsas
      @nickchapsas  2 года назад +1

      It depends on the lifetime of the handler. The default is transient yes, but you can change it.

  • @computer9764
    @computer9764 2 года назад +1

    Shoutout for Reactive Extensions ✌

    • @nickchapsas
      @nickchapsas  2 года назад +1

      That’s something that I’ll be taking a look at very soon btw

    • @fatalfailure6240
      @fatalfailure6240 2 года назад

      If I can use IObservable and Rx, I try to use them every time. DryIoc has a simple built-in mediator which I added IObservable into, works great. Always thought Mediatr was a bulky library but it seems it's straightforward as well.

  • @easycodeunity3d14
    @easycodeunity3d14 2 года назад +1

    Nick, it's amazing but not that new. Check UniRx MessageBroker class usage.

  • @JacobSmith-hj2kt
    @JacobSmith-hj2kt 2 года назад

    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(...); ?

  • @Gruggo
    @Gruggo 2 года назад +1

    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?

    • @nickchapsas
      @nickchapsas  2 года назад +1

      It’s for deterministic execution. Code can be moved around, the project might be referenced by another project etc

  • @antonmartyniuk
    @antonmartyniuk 2 года назад +5

    I like assigning the empty default value to the event to prevent any checks in the code. public event EventHandler ButtonPressed = delegate {};

  • @DevDunkStudio
    @DevDunkStudio 2 года назад

    In Unity there are special UnityEvents, which are godly to use

  • @logicchild
    @logicchild 2 года назад +1

    It's not dead; it's just not a best practice in dependency injection :)

  • @emoney9979
    @emoney9979 2 года назад +6

    Can we talk now about Event Sourcing in Event Driven Architecture? :D Thanks for highly informative video as always!

    • @megaman2016
      @megaman2016 2 года назад +1

      Yes this would be interesting

    • @nickchapsas
      @nickchapsas  2 года назад +14

      There is a video I’m really proud of about event sourcing coming

  • @pchoudhary
    @pchoudhary 2 года назад

    Event themselves are not obsolete. How do you represent domain side effects? Barebone events are errorprone and there weak events, observables etc to help with that.

    • @nickchapsas
      @nickchapsas  2 года назад +1

      Sure but I refer to barebone events, not other implementations of the concept

  • @Xero_Wolf
    @Xero_Wolf Год назад

    I think I've been spoiled by using GDScript too much lol. Signals are basically Godot's version of events but it's so much simpler to implement. You setup, connect to and emit a signal in just three lines of code. I guess because I'm new to C# but this is gonna take some time to sink in.

  • @ThugLifeModafocah
    @ThugLifeModafocah Год назад

    This is a really good content. Thank you.

  • @rolandtennapel5058
    @rolandtennapel5058 2 года назад

    So...why are all the GUID's different when I do this using events (used custom delegate / EventHandler and only System.GUID as an argument instead of a System.EventArgs)? 😅 I think the objection here is purely on the pre-built System.EventArgs, not so much the whole event system (which doesn't rely on it AT ALL, it's just the default and recommended use of). The only reason this should fail is because the System.GUID instance wasn't destroyed yet; The Argument object hasn't been disposed of yet. If the effects are the issue, then the solution should be focussed on the problem... I guess what I'm saying is that if you want all your listeners to have a different GUID, just make an argument object with GUID { get { return System.Guid.NewGuid(); } }, or accept that what you put in (in Invoke) is what you'll get out (as it should)...

  • @oldclient
    @oldclient 2 года назад +2

    This video blog is confusing for me. Just don't mix the concepts of Event, 'scheduler' and 'service controller' (aka MediatR). MediatR has its pros and cons. Among its disadvantages is we can't see from a Controller who's running our request. In my opinion, from project to project, we have to choose the right tool. There are cases when Events are the best option, there are cases when we have to use the good old school Timer class and there are cases when it's better to split event requests and handlers and control their runtime under common Generic interface behavior via MediatR.

    • @nickchapsas
      @nickchapsas  2 года назад

      I don’t know why you call MediatR a “service controller”. What mediator is is very specific and it’s nothing like what you describe.. There is no scheduler here either. The interval is used for demoing the events as something that would happen in a background service, not for any scheduling purpose.

    • @oldclient
      @oldclient 2 года назад +1

      @@nickchapsas That's why I quoted those words. MediatR' requests represent any class which implements IRequest interface. MediatR' handlers represent any class which implements IRequestHandler interface. A class in CLR .Core can represent any behavior: a Data model, an Attribute, an EventArg, a DLL library, an Assembly (including late binding) even a Win Service. At some degree it's hard to put a line between App, Process, Assembly, AppDomain, Service, Context, because all these entities can represent each other. Events "operate" with methods while MediatR "operate" with classes, which is a different level of abstraction. This is an analogy to the Win OS' Service or Unix daemon model.

  • @jannickbreunis
    @jannickbreunis 2 года назад

    Me finally getting a hang with events.
    Nick: nah not relevant..
    Gotta watch this

  • @MaskHysteria
    @MaskHysteria 2 года назад

    First time I've heard the Observer design pattern is obsolete considering how many browser based SPA frameworks rely on it. Events are, more or less, C#'s native implementation.

    • @nickchapsas
      @nickchapsas  2 года назад

      Observer and events are not the same

  • @shaihulud4515
    @shaihulud4515 2 года назад

    Now, that I finally wrapped my head around events and event handling, it's outdated. I'm too old for this...

  • @kevinmerrell9952
    @kevinmerrell9952 2 года назад

    Good post. Thank you.

  • @Creatorph
    @Creatorph Год назад

    The Func and Action are more used nowdays, my college hasen't heard of delegates since he graduated ^^

  • @benniebees
    @benniebees 2 года назад

    But why do we need events, or a library for this? On types that expose "events" just create a dictionary of Action. When the event is fired, all Actions in the dictionary are executed. To subscribe, call the public Sub(Action a) method that returns a key, and pass the key into a public Unsubscribe(Key k) method to unsub.

    • @nickchapsas
      @nickchapsas  2 года назад

      Yeah you can totally do that. I wanted to show us safer way that you can’t get wrong

    • @wobuntu
      @wobuntu 2 года назад

      @iLikeCookiesQ totally agree. Much simpler, no need for yet another extra nuget lib, easier to read, etc. Not everything needs to be blown up into its own class hierarchy

  • @samplecode
    @samplecode 2 года назад

    I’d be interested to hear how much RX has replaced old school event handling.

    • @nickchapsas
      @nickchapsas  2 года назад +2

      There is an RX video coming as a follow up to this one

  • @MrEnvisioner
    @MrEnvisioner 2 года назад

    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?

  • @EspenSkaufel
    @EspenSkaufel 2 года назад +1

    🍎 and 🍊. Not deprecated at all. What about file system, network or other devices? I has to be a callback or event.

    • @nickchapsas
      @nickchapsas  2 года назад

      Not at all. You can hook up whatever you want in there, they don’t have to be events. Also a callback and an event are 🍎 and 🍊

    • @EspenSkaufel
      @EspenSkaufel 2 года назад

      ​@@nickchapsas My point was that events should not be used in the same circumstances as mediator notifications, but events and callbacks can. If I were to create something like the FileSystemWatcher, using mediator would be a bizarre implementation. Also, it would be fun if libraries started to implement events as mediator notifications and disagreed on what version or library to use.

    • @nickchapsas
      @nickchapsas  2 года назад

      @@EspenSkaufel Ofc they are not the same, I never said they are, but the Notifications implementation of MediatR can give you an argueably better alternative for this usecase. Ofc you would not use MediatR for the usecase you mentioned. An observer pattern would be way better here. Events can be used to implement callbacks. Notifications can be used to implement events. Events as a concept is the root, not the end. Event he callbacks you mention aren't events. They are just callbacks triggers by something. That something can be events but it can be something else too.

    • @EspenSkaufel
      @EspenSkaufel 2 года назад

      @@nickchapsas Sorry for being annoying, bad habit. Your title triggered the response, as I expect to see developers trying to avoid using events at all costs after watching this. Knowing when to use what is why experience matters in software development. Just like with inheritance, it is bad most times, good sometimes 🥴.

  • @ARVash
    @ARVash 2 года назад +1

    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.

  • @NotMarkKnopfler
    @NotMarkKnopfler 2 года назад

    My first question: How on earth did you get multiple projects to show up in Rider? I can't work it out, and even the forums for Rider give the impression that they are not going to add this feature. ??

  • @SirPrsty
    @SirPrsty 2 года назад

    thanks master, but we can use new guid before publish? its same right? and use transient services

  •  2 года назад +1

    Can you make a video about NativeAOT?

  • @mehdisalehi
    @mehdisalehi 2 года назад

    Nick Why not replace C# event with Reactive Extensions? Need to know your opinion about it

  • @TheCMajor9th
    @TheCMajor9th 2 года назад

    exceptional video ty

  • @jorgerochagualtieri
    @jorgerochagualtieri 2 года назад

    What about performance? Does MediatR delivery the same performance as old fashioned events?

  • @RoughSubset
    @RoughSubset 2 года назад +3

    Nick you such a legend bro, I learn so much from you, keep it up!