✅ How can I get multiple responses from raising an event?

Typically, when you raise an event you don't expect a response. However, you can define you own delegate that has a non-void return type which will mean that a subscriber can return a value. Alternatively, you can pass a mutable object in the EventArgs which the subscriber can change and then that change can be seen by the publisher. I want to extend this to the case where there are multiple subscribers. The first option doesn't work since you only get the return value of the last subscriber to execute. You can put a List in the EventArgs and then have the subscribers add their responses to it, however, I don't see any way of doing this that would ensure that each of the subscribers cannot see the responses of other subscribers while allowing the publisher to see all of the responses. The best I have come up with is to have the EventArgs be readable once (e.g. raising an exception or setting a flag if it is tried to be read more than once) which would allow the publisher to see if any of the subscribers have been looking at the other responses. Is there a better way of doing this?
14 Replies
Thinker
Thinker2y ago
You could create a simple wrapper around a list and pass that into the event args.
internal sealed class EventArgsList<T>
{
internal List<T> List { get; }

public EventArgsList()
{
List = new();
}

public void Add(T item) => List.Add(item);
}
internal sealed class EventArgsList<T>
{
internal List<T> List { get; }

public EventArgsList()
{
List = new();
}

public void Add(T item) => List.Add(item);
}
The Orange Tea Frog
How does this stop the subscribers from reading the responses from other subsribers? A subscriber could just look at List A subsriber could even remove the responses of other subscribers
Thinker
Thinker2y ago
ah, I assumed your subscribers were in another assembly
The Orange Tea Frog
Unfortunately not Otherwise yeah that would have worked I think I might have the solution actually, The EventArgsList could take a list as an arg and then not allow any reading
Thinker
Thinker2y ago
ye
The Orange Tea Frog
Thanks for the help though
DaVinki
DaVinki2y ago
Well when you raise an event you generally pass the object that raised it Instead of passing just any object, it could be objects that implement an interface for receiving data from listeners Implementing that could be done a million different ways First thing that comes to mind would just be having a record or something be added to a list property provided by the interface
cathei
cathei2y ago
public interface IEventArgList<T>
{
void Add(T item);
}

public class EventArgsList<T> : IEventArgList<T>
{
// ...
}
public interface IEventArgList<T>
{
void Add(T item);
}

public class EventArgsList<T> : IEventArgList<T>
{
// ...
}
and pass as interfaces catlurk
reflectronic
reflectronic2y ago
use Delegate.GetInvocationList()
reflectronic
reflectronic2y ago
this will return indiviual delegates for each method in the invocation list then you can collect the results from invoking each of these delegates
The Orange Tea Frog
These are all good ideas. Thanks guys
Omnissiah
Omnissiah2y ago
uhm an event that returns a value is an rpc
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server