C# Event Subscription - c#

In C# what is the advantage of
public class blah
{
public event EventHandler Blahevent;
}
versus
public class blah
{
private event EventHandler blahevent;
public event EventHandler Blahevent
{
add
{
blahevent+=value;
}
remove
{
blahevent-=value
}
}
}
or vice versa.
does the first one open you up to blahinstance.Blahevent = null, or blahinstance.Blahevent(obj,even)

There is no advantage to explicit implementation of the add/remove methods unless you want to do something different. Possible reasons:
Perhaps take control of the event backing code yourself (to directly link to some other event rather than going though a pointless cascade for example)
do something else in addition on add or remove
Change security demands on the add or remove
expose the underlying delegate
What the default implementation does is maintain a private hidden delegate field which is replaced each time a delegate is added or removed. For most cases there is no need to do any of the above but the flexibility is there.

The second one has the option of controlling exactly what happens when the specified event is subscribed to or unsubscribed from if there is specific logic that needs to run in addition to adding or removing the pointer.

You can exclude the delegate from serialization by using the [field: NonSerialized()] attribute on the private field.

You can place a breakpoint on the latter for debugging purposes. Sometimes this can be really useful (although after debugging I switch it back to the former).

Related

The event 'SerialPortUtil.PortListener<DataObject,DataProcessor>.OnNewDataReceived' can only appear on the left hand side of += or -= SerialPort C#

I have a problem with the following code
public event PortListener<DataObject, DataProcessor>.NewDataHandler OnNewDataReceived
{
[MethodImpl(MethodImplOptions.Synchronized)]
add
{
this.OnNewDataReceived += (PortListener<DataObject, DataProcessor>.NewDataHandler)Delegate.Combine(OnNewDataReceived, value);
}
[MethodImpl(MethodImplOptions.Synchronized)]
remove
{
this.OnNewDataReceived -= (PortListener<DataObject, DataProcessor>.NewDataHandler)Delegate.Remove(OnNewDataReceived, value);
}
}
Event OnNewDataReceived error! How to fix it
If you want to manage event add/remove yourself, it's up to you to store the delegate1, separately from the event. Your code inside add and remove is trying to treat OnNewDataReceived as a delegate, which it isn't2.
So, add a backing field with the correct delegate type and manipulate that inside your add and remove accessors.
So you'd have something like:
private PortListener<DataObject, DataProcessor>.NewDataHandler newDataHandlers;
public event PortListener<DataObject, DataProcessor>.NewDataHandler OnNewDataReceived
{
[MethodImpl(MethodImplOptions.Synchronized)]
add
{
newDataHandlers += value;
}
[MethodImpl(MethodImplOptions.Synchronized)]
remove
{
newDataHandlers -= value;
}
}
(Mucking about with Delegate.Combine was also pointless since += does that job)
As it currently stands though, this whole thing looks like wasted effort. I would guess that you're doing this to make adding and removing event handlers "thread safe" by applying the Synchronized option. But:
When compiling a field-like event, the compiler automatically creates storage to hold the delegate, and creates accessors for the event that add or remove event handlers to the delegate field. The addition and removal operations are thread safe
(My emphasis)
So, really it should just be:
public event PortListener<DataObject, DataProcessor>.NewDataHandler OnNewDataReceived;
1Or a list of delegates, or some other data structure. After all, that's the reason why you're writing the add/remove handlers in the first place, isn't it, to manage how the event's delegate list is stored?
2There is some magic when you use a field-like event which makes the event resemble a delegate under some circumstances. But by providing your own accessors you've opted out of this being a field-like event.

Create a special dictionary<T, EventDelegate<T>> with generic delegate EventDelegate<T>(T e) where T : GameEventBase

I have a game with many classes that need to listen to events. But under certain circumstances, those classes are destroyed or disabled. When that happens, I need to remove their listening methods from the events manager delegate table.
I don't want to modify the EventsManager and I would like to each class that adds any events to it to know which events it added.
I'm currently using something like this do add and remove the events in each class:
void AddEventsListeners() {
EventsManager.AddListener<OnClickDown>(OnClickDownHandler);
EventsManager.AddListener<OnClickUp>(OnClickUpHandler);
EventsManager.AddListener<OnClick>(OnClickHandler);
}
void RemoveEventsListeners() {
EventsManager.RemoveListener<OnClickDown>(OnClickDownHandler);
EventsManager.RemoveListener<OnClickUp>(OnClickUpHandler);
EventsManager.RemoveListener<OnClick>(OnClickHandler);
}
Those OnClick are all derived from GameEventBase, and the OnClickHandler are methods declared as
void OnClickDown(OnClickHandler e) {}
to match the delegate that is used in the EventsManager, which is declared as
delegate void EventDelegate<T>(T e) where T : GameEventBase;
I want to be able to fill a special hash table named, say, events, that has keyvalue pairs like
<T, EventDelegate<T>> where T: GameEventBase
That is, I want to be able to do events.add(OnClick, OnClickHandler), where OnClickHandler is declared as
OnClickHandler(OnClick e) {}
And I want adding to fail if OnClickHandler where defined, for example, as
OnClickHandler(OtherGameEventBaseDerivedEvent e) {}
That requirement translates to me wanting type safety in that special dictionary.
One of my attempts involved not a dictionary, but a way to decide which method to call, between the AddListener and RemoveListener
I didn't like it because it introduces a parameter to the method and the code reads really weird with it. It does work, and does reduce the repetition, but is too ugly.
I create a AddOrRemoveAllListeners(AddOrRemove addOrRemove), which I populated with calls to AddOrRemoveListener for each event.
Now all I had to do is AddOrRemoveAllListeners(AddOrRemove.Remove) or AddOrRemoveAllListeners(AddOrRemove.Add), to add or remove my events.
enum AddOrRemove {
Remove,
Add
}
void AddOrRemoveListener<T>(EventsManager.EventDelegate<T> del, AddOrRemove addOrRemove)
where T : GameEventBase {
switch (addOrRemove) {
case AddOrRemove.Remove:
EvMan.RemoveListener<T>(del);
break;
case AddOrRemove.Add:
EvMan.AddListener<T>(del);
break;
}
}
Another attempt involved creating the type
class EventsDictionary<T> : Dictionary<T, EventsManager.EventDelegate<T>> where T : GameEventBase { }
And using it like this:
EventsDictionary<GameEventBase> events = new MyCustomDictionary<GameEventBase>();
void AddEventHandlerPairToEventsDictionary<T>(T e, EventsManager.EventDelegate<T> handler) where T : GameEventBase {
if (!events.ContainsKey(e)) {
events.Add(e, handler);
}
}
But the events.Add(e, handler) fails and forces me to declare the handler as
EventsManager.EventDelegate<GameEventBase>
instead of
EventsManager.EventDelegate<T>
If I do that, I could add keyvalue pairs that don't make sense in that events type, i.e., I lose the event handling type safety.
I want to have such a structure because I don't like all those repetitions. It would be really bad if someone forgot to remove an event in the RemoveEventsListeners().
Having such a dictionary, I could use a foreach loop to add/remove the handlers to the EventsManager, which would be really nice.
As for performance, this is for a game and it needs to have good performance. Those adding/removing of events can happen a lot (sometimes hundreds of times per frame) because a lot of objects are destroyed (can't leave null handlers in the EventsManager) or disabled (need to stop listening to everything until enabled again) all the time. This means reflection and lots of casting/boxing or anything that creates lots of garbage collected objects is out.
I'm, of course, open to suggestions as to other ways to approach this.
Thanks for your assistance!
I'm attaching the relevant parts of the EventsManager being used (The RemoveListener() is analogous to the AddListener). The GameEventBase is just an empty shell. It isn't a .NET event nor uses EventArgs.
public class EventsManager : ManagedBase {
public delegate void EventDelegate<T>(T e) where T : GameEventBase;
private delegate void EventDelegate(GameEventBase e);
private readonly Dictionary<Type, EventDelegate> delegates = new Dictionary<Type, EventDelegate>();
private readonly Dictionary<Delegate, EventDelegate> delegateLookup = new Dictionary<Delegate, EventDelegate>();
public void AddListener<T>(EventDelegate<T> del) where T : GameEventBase {
// Early-out if we've already registered this delegate
if (delegateLookup.ContainsKey(del)) {
return;
}
// Create a new non-generic delegate which calls our generic one.
// This is the delegate we actually invoke.
EventDelegate internalDelegate = (e) => del((T) e);
delegateLookup[del] = internalDelegate;
EventDelegate tempDel;
if (delegates.TryGetValue(typeof (T), out tempDel)) {
delegates[typeof (T)] = tempDel + internalDelegate;
}
else {
delegates[typeof (T)] = internalDelegate;
}
}
public void Raise(GameEventBase e) {
EventDelegate del;
if (delegates.TryGetValue(e.GetType(), out del)) {
del.Invoke(e);
}
}
}
Your problems seem to be solved if you use the EventAggregator pattern.
There is a short description of it by Martin Fowler
Some very good implementations of it already exist, for example in caliburn micro and
Microsoft Prism
The general idea is that you simplify event registration and deregistration and have a single source of events for many objects.
I never had performance issues with it. You simply put a _eventAggregator.Subscribe(this) when you want to start listening to events for an object and Unsubscribe if you want to stop. Whereever you want to fire an event, just publish it, EventAggregator does the routing.
This once again looks like an XY problem. OP seems to want to have a central place to handle event handlers, registration and disposal. The OP has gone down the route of trying to create a pattern that deal with this in a generic way, but has not looked into the state of the art regarding how this problem is typically solved. He has now come up against a problem in his design and is now asking for a solution to THAT problem, rather than the original problem of event handlers.
There are two good solutions to event handler registration lifecycle management that I know of in .net.
Weak Event Handler
You state that "It would be really bad if someone forgot to remove an event in the RemoveEventsListeners()." Yet do not actually mention WHY it is bad. Typically the only reason for this being bad is that the event handler will now keep an object in reference, that should be collected. With weak reference event handlers, the GC will still be able to collect your object, even when it subscribes to an object that is still alive.
Rx.Net
Rx.Net abstracts event registrations into IDisposables, which you can tie to the object's lifetime, assuming of course you want to control the lifetime of the registrations.
However I actually find the IObservable pattern much nicer to work with than event handler pattern, mostly because C# lacks first class support for event handlers (this is not the case with F#).
F#
Most of your problems will have stemmed from the short sighted design of events keyword handling in C# (specifically not making events a first class construct). F# however does support first class events, and thus should be able to support the pattern you are trying to construct.
Thus with this option you should scrap your code base and rewrite it in F#.
*EDIT added tongue in cheek option of rewriting in F#.

Unsign all event listeners, C# code example

I have a C# class which introduce a new custom event type, and allows users add or remove listeners to it. Also I implement a method which revoves all event listeners during dispatch;
public event EventHandler DataCommited;
private void DetatchListeners()
{
if (DataCommited != null)
{
foreach (EventHandler eh in DataCommited.GetInvocationList())
{
DataCommited -= eh;
}
}
}
It is possible to implement a method which will be taking DataCommited event as an argument. So, I can unsign a set of events using one method. I tried a lot ways implementing it, but unfortunately failed to do it. I wonder if it is actually possible and how. Thank you!!!
It is possible to implement a method which will be taking DataCommited event as an argument.
Well, not really. You can take an EventInfo, but that's all. It's important to understand that this statement:
public event EventHandler DataCommited;
actually creates two things:
An event, which code in other classes can subscribe to and unsubscribe from
A field of type EventHandler, which you can use to call the handlers, or get each one individually.
A simpler implementation of your current code would simply be this:
public event EventHandler DataCommited;
private void DetatchListeners()
{
DataCommitted = null;
}
Unsubscribing from a field-like event just changes the value of the field, after all.
However, if you have an EventInfo, you don't know how that event is implement. It may be backed directly by a field - it might not be... there's no general way of asking an event for its current handlers, or setting a new list of handlers. All you can do directly with an event is subscribe and unsubscribe.
If you only use field-like events, you could use reflection to find the name of the field and set the value to null. You can't do it in general though.
See my article on delegates and events for more information.

what if I need to execute event handlers in certain order?

I have event, for example like that:
public event EventHandler<NewReadyMessageEventArgs> NewReadyMessage
The problem is that i need to attach two handlers to it and i need to execute one before another (because the last one depends on first one). I.e. I need certain order of handlers execution.
I understand that in reality handlers will be executed one by one and so I just need to attach them in right order but that would be very error-phrone design.
I want to create separate handler and attach it. In this handler I just want to execute my two handlers in right order. What do you think and what would you suggest?
The problem is that i need to attach two handlers to it and i need to execute one before another (because the last one depends on first one)
In this case, I would rethink your design. It likely makes more sense for the "first" handler to raise its own event.
The second handler could attach to that event, and have the results of both items.
I would not rely on the internal implementation to ensure that the handlers get called in a specific order.
If the handlers can't know about each other but you need them to run in a certain order I would create a "parent" handler that calls the other two handlers in the correct order.
I would suggest implementing your own add implementation if you don't want the default multicast delegate with the default event add/remove implementation.
For more information see http://msdn.microsoft.com/en-us/library/cc713648.aspx
In case it wasn't obvious, if you don't use the default multicast delegate, invocation of subscribers needs to be implemented manually. The above link details how to write custom add/remove to use a multicast delegate. This answer assumes you don't use a multicast delegate For example, something like:
private List<EventHandler> eventList = new List<EventHandler>();
public event EventHandler Event1
{
add { eventList.Add(value); }
remove { eventList.Remove(value); }
}
private void RaiseEvent1()
{
foreach(var e in eventList)
{
e(this, EventArgs.Empty);
}
}
Use a SortedList if you want a specific order...
It sounds like this might be a place where you just need to have multiple (2) events.
If the order is important have two events, and have one that is simply fired right after the other. You can see this at, for example, the page lifecycle in ASP. There are lots of events, and in some cases they're all fired one after the other with thing really inbetween them other than a guarantee that all handlers of the previous event are run. That sounds just like your case here.

What use cases exist for non-static private or protected events?

What purpose do protected or private (non-static) events in .NET really serve?
It seems like any private or protected event is more easily handled via a virtual method. I can (somewhat) see the need for this in static events, but not for normal events.
Have you had a use case before that clearly demonstrates a need or advantage for a non-static protected or private event?
Here's a slightly bizarre but real-world scenario I implemented once. You have machine-generated and user-generated halves of a partial class. The machine-generated half contains code which wishes to inform the user-generated half when some event occurs. But the user-generated half might not care to do anything, or it might care to do rather a lot. It seems rude of the machine-generated half to require that the user-generated half implement a particular method in order to handle a message they don't have any interest in listening to.
To solve this problem, the machine-generated half could fire on a private event. If the user-generated half cares, it can subscribe the event. If not, it can ignore it.
This scenario is now addressed more elegantly by partial methods in C# 3, but that was not an option back in the day.
Seems to me that a good example of where a private event is useful is in component/control building, often you may have a component that is a composite of 1 or more other components, private events that contained components can subscribe to is a handy and easy implementation of an observer pattern.
Edit:
Let me give an example...
Say you are writing a Grid type control, and inside of this control you would most likely have a bunch of contained classes that are created dynamically Rows, Cols, headers etc for example, say you want to notify these contained classes that something they care about has happend, say a Skinning change or something like that, something that you don't necesarrily want to expose as an event to the grid users, this is where private events are handy, simply have one or 2 handlers and as you create each instance of your row or col or whatever attach the handler, as otherwise you just have to write your own observer mechanism, not hard, but why when you dont have to and you can just use multicast events.
Nested types have access to the enclosing type's private and protected events. I've used this feature to notify child controls (the nested type) of state changes in the parent control (the enclosing type) in a Silverlight application.
Sorry to drag up an old thread, but I use private events with impunity in one of my projects, and personally, I find it's a good way of solving a design issue:
Here's the abbreviated code:
public class MyClass
{
private event EventHandler _myEvent;
public ExternalObject { get; set; }
public event EventHandler MyEvent
{
add
{
if (_myEvent.GetInvocationList().Length == 0 && value != null)
ExternalObject.ExternalEvent += HandleEvent;
_myEvent+= value;
}
remove
{
_myEvent-= value;
if (_myEvent.GetInvocationList().Length == 0)
ExternalObject.ExternalEvent -= HandleEvent;
}
}
private void HandleEvent(object sender, EventArgs e)
{
_myEvent.Raise(this, EventArgs.Empty); // raises the event.
}
}
Basically, MyEvent is only ever raised in the event handler of ExternalObject.ExternalEvent, so if there's no handlers for MyEvent then I don't need to attach a handler to the external event, speeding up the code slightly by saving a stack frame.
Not only the current instance can access a private member. Other instances of the same type can too! This enables some scenarios where this access control may be useful.
I am thinking of a tree structure where all nodes inherit a certain type and a private/protected event allows to propagate leaf events to their parents. Since they are the same type, the parent can register to the child's private event. Yet any client of the tree structure cannot.
I can definitely see a use case in a directory like storage system where where each directory needs to propagate its last modified date to its parent for example.

Categories

Resources