patterncsharpModerate
Type-Safe Event System
Viewed 0 times
typesystemsafeevent
Problem
I have recently started writing C# from a strong JavaScript background, and found myself wanting to do something I do all the time in JavaScript: events.
Since I have a type system at my disposal, I figured I'd make use of it and make the event system type safe.
A quick note on existing options:
C#'s built-in
Unity's built-in
The code compiles and works, but I am wondering if there's a more elegant solution - or even if there's just a way I could reduce the boilerplate in my own solution. (Generics seem to cause most if not all of the boilerplate, but I didn't see a better way to get type-safety in callbacks.)
Here's how it is used:
Here's how it is structured:
Since I have a type system at my disposal, I figured I'd make use of it and make the event system type safe.
A quick note on existing options:
C#'s built-in
event library didn't really appeal to me - for one, I don't really like the syntax (eg listeners += callback), but more than that, I wanted type-safety in the callbacks. (ie, I want the callback to be something like Action, not public void delegate SomeEventHandler(object sender, EventArgs args)).Unity's built-in
UnityEvent looks pretty good, but these aren't collected and managed in any way. I decided to roll my own Events to go with my EventManager, but I think I could adapt it to use UnityEvent fairly easily.The code compiles and works, but I am wondering if there's a more elegant solution - or even if there's just a way I could reduce the boilerplate in my own solution. (Generics seem to cause most if not all of the boilerplate, but I didn't see a better way to get type-safety in callbacks.)
Here's how it is used:
using EventSystem;
// create SomeEvent - uses a class stub, not sure how I feel about that
public class SomeEvent : BasicEvent { }
// listen to it somewhere else in the codebase...
EventManager.On((param) => / ... /);
// and trigger it somewhere different still...
EventManager.Trigger(someParameter);
Here's how it is structured:
namespace EventSystem
EventManager.cs, a static class that can be used to listen to / detach from and trigger events
EventBehaviour.cs, an abstract class that "registers" an event with theEventManagerusing Unity'sAwake () { ... }- basically glue between the event system and Unity
IEventListener.cs, generic interfaces that define a type-safe listener, and have extension methods for implementing listenerInvokemethods for any of the defined generics
- `BasicListener.c
Solution
C# events are type-safe. The common (and recommended) pattern is to use
The problems that I can see in this pattern are:
If you're set on not using this pattern, I think you should still use
The simplest version of that is just:
EventHandler, where T is a custom type deriving from EventArgs, containing the data of the event. You should use this pattern if possible, especially if you're writing a library that will be used by third parties.The problems that I can see in this pattern are:
- The
senderparameter is alwaysobject. It's either not useful (because you can access the object directly thanks to lambdas) or requires casting.
- The
eventArgsparameter should derive fromEventArgs. This means you need to litter your code with lots of types that derive fromEventArgs, even if the data of the event is just a single value.
If you're set on not using this pattern, I think you should still use
event, just not with EventHandler.The simplest version of that is just:
public event Action SomeEvent;Code Snippets
public event Action<SomeParameter> SomeEvent;Context
StackExchange Code Review Q#120664, answer score: 11
Revisions (0)
No revisions yet.