-2

I have a situation where multiple classes are registering interest with another class to observe a certain property's value. This is being done by using delegates like so:

public delegate void ObservingHandler (object value);

Dictionary<ObservingHandler, ObservationInfo> _handlers = new Dictionary<ObservationHandler, ObservationInfo>();

public void register(ObservingHandler handler) {

    // Observation info is created here and is just a struct
    _handlers.Add(handler, info);
}

This works great and is really useful but currently when a registered object is released it has to tell the relevant class that it no longer wants to receive notifications. Otherwise I get NULL reference exceptions.

Currently this means I can't use lambda expressions because the observation handler is the key in the dictionary (and so needs to be the same instance when it comes to removing it).

What I would like to do is to check that each ObservationHandler has a valid and instantiated class behind it before it is called. This way responsibility is taken away from the listening class.

Is there some way in Func or delegate to check the receiver of the function is alive and well?

EDIT:

The full source code comes from my project called SFCore on GitHub.

Rob Sanders
  • 5,197
  • 3
  • 31
  • 58
  • 2
    "Otherwise I get excetpions" - what exceptions? It's not really clear what you mean - please show a [mcve] demonstrating the problem. – Jon Skeet Apr 21 '16 at 15:04
  • The `ObservingHandler` is a reference to a method in an observing class. If the observing class is released, the `ObservingHandler` contains a reference to a method in a null class. I believe the exception is a null reference exception. So right now I have to have the observing class de-register itself prior to release but I would like to be able to tell if the `ObservingHandler` has a instantiated observer attached to it. – Rob Sanders Apr 25 '16 at 10:16
  • Rather than "believing" that the exception is a NullReferenceException, why don't you show us an example? I'd expect the ObservingHandler reference to keep the target alive automatically - there's no "release" here. Basically, until you can reproduce the problem in a concise form, it's going to be very difficult to help you. – Jon Skeet Apr 25 '16 at 10:19
  • Believe is a turn of phrase. It IS a null reference exception. The problem arises specifically with unity when a component that is listening to another is destroyed by the game engine. I'm not going to upload an entire project, however I feel I've explained the problem in detail now. Thanks for your input. – Rob Sanders Apr 25 '16 at 10:25
  • I didn't ask you to upload a whole big project - but you should work to reproduce it in a short but complete example. Also, if you believe your problem is Unity-specific, you should put that in the question and the tags - this is the first mention of Unity. An no, you *haven't* explained the problem in enough detail, IMO. Put it this way: I still can't help you, and I suspect I'm not the only one. You can either decide to leave the question as it is, which will leave it of less use to future readers and with a limited audience who can help you, or work to make it better for everyone. – Jon Skeet Apr 25 '16 at 10:38
  • There isn't a specific problem to highlight. The question is: `Is there some way in Func or delegate to check the receiver of the function is alive and well?` Your answer so far is to say that there is no "release". Essentially the ideal answer is `yes` or `no` and a demonstration of how to check the receiver. – Rob Sanders Apr 25 '16 at 13:05
  • If you're getting a `NullReferenceException`, that's a problem, and you should provide a short but complete program demonstrating it. There's no concept of "alive and well" in .NET, and the target of a delegate will *not* be garbage collected, so that's not the issue. – Jon Skeet Apr 25 '16 at 13:15

2 Answers2

1

I'd go with the .NET event model and let the responsibility stay with the listener, after all if your test fails for any reason, your receiver won't be notified anymore.

What I would do, is, while notifying the listeners, catch any exceptions that may arise.

If an exception arises that is due to a class no longer existing (can't be more specific you didn't gave us the exact exception name) you would then either ignore it (thinking that it's only a one-time mistake) OR remove it from the dictionary.

Again that's what I would do, there are surely other methods to achieve that.

Irwene
  • 2,807
  • 23
  • 48
  • Thanks, that's a good idea. Is there any way that you know of to tell prior to notifying a listener if the listener is actually in existence? I'm assuming that `event` does this but I have no idea how. – Rob Sanders Apr 25 '16 at 10:19
0

The Observer pattern in C# is achieved with events. Using the event key word would be advised based on your description.

You won't need to keep track of the callbacks to at that level of holding a Dictionary as you have in your example. All you do in your call is: fire the event.

Bruno Garcia
  • 6,029
  • 3
  • 25
  • 38
  • But you still need to check when firing the event that you have observers, if you don't you're gonna have some nice `NullReferenceException` – Irwene Apr 22 '16 at 06:52
  • 1
    not if you always have at least one listener: event EventHandler MyEvent = (s, e) => { }; – Bruno Garcia Apr 22 '16 at 07:51
  • Well I took the habit of checking for null in these cases :) But yeah that's another way to look at it – Irwene Apr 22 '16 at 07:57
  • The reason I'm not using an event is so that I can bundle `ObservationInfo` with the handler. How could I do this with events? – Rob Sanders Apr 25 '16 at 10:38
  • What do you mean by bundle it together? And when is that value used? – Bruno Garcia Apr 27 '16 at 05:36