0

I'm trying to implement HTTP server sent events as shown in this Stack Overflow answer. The answer fires off a notification to all subscribers on event. I'd like to have only a specific client receive notification for an event (so only the client who did something to trigger an event will be notified, instead of everyone).

I'm using EventHandlerList to register handlers, using a Guid as key. Relevant snippet of code:

public class MessageRepository
{
    private readonly EventHandlerList _eventHandlerList;

    public MessageRepository()
    {
        _eventHandlerList = new EventHandlerList();
    }

    public void Subscribe(Guid guid, Delegate handler)
    {
        _eventHandlerList.AddHandler(guid, handler);
    }

    public void Unsubscribe(Guid guid, Delegate handler)
    {
        _eventHandlerList.RemoveHandler(guid, handler);
    }

    public void Notify(Guid guid, string message)
    {
        _eventHandlerList[guid]?.DynamicInvoke(this, new Message(message));
    }
}

Unfortunately, _eventHandlerList[guid] always comes back as null. I've verified that a similar implementation where Dictionary<Guid, Delegate> is used in place of EventHandlerList works correctly. Why?

mmking
  • 1,564
  • 4
  • 26
  • 36
  • Guid is a struct. And unfortunatly EventHandlerList compares keys with == operator. – shingo Jan 12 '22 at 04:35
  • @shingo The guids are the same (set to Guid.Empty currently for testing), so I don't think that's the issue. == operator does value check and comes back true, as expected. – mmking Jan 12 '22 at 04:46
  • If compares the reference of 2 objects, check my answer. – shingo Jan 12 '22 at 04:54
  • _"operator does value check and comes back true, as expected"_ - no, it [does not](https://rextester.com/NGMD48509) – Guru Stron Jan 12 '22 at 05:25

1 Answers1

2

Guid is a struct and unfortunatly EventHandlerList compares keys with == operator.

var guid = Guid.NewGuid();
object key1 = guid;
object key2 = guid;
Console.WriteLine(key1 == key2); // False

The document suggests using an empty object as a key. If you want to use guid, you have to keep and use the same reference of it.

object guid = Guid.NewGuid();
_eventHandlerList.AddHandler(guid, handler);
Console.WriteLine(_eventHandlerList[guid]);

Dictionary (and other collection in .net) uses Equals to compare keys, that's why it works for guid.

shingo
  • 18,436
  • 5
  • 23
  • 42
  • You're right. Brain scrambled up Equals and == last night. I think it might be easier to stick with dictionary in this case. Thanks! – mmking Jan 12 '22 at 15:34