tags:

views:

303

answers:

3

I'm trying to use events to use the nice += -= syntax.

Here is my problem: I have a lot of different events, so instead of creating many events, I would like to use only one, where the registrant additionally supplies an additional parameter (string[]) detailing which (sub)events one wants to listen to.

The is basically what I'm doing now:

public delegate void dMethod(int index);
private Dictionary<string, dMethod> events;
public void RegisterEvents(dMethod m, string[] subEvents){
    foreach(string subEvent : subEvents){
        events[subEvent] += m;
    }
}

Instead I would like to do something like this:

public delegate void dMethod(int index);
private Dictionary<string, dMethod> events;

public event dMethod Events(string[] subEvents) {
 add {
        foreach(string subEvent : subEvents){
            events[subEvent] += value;
        }
 }
 remove {
        foreach(string subEvent : subEvents){
            events[subEvent] -= value;
        }
 }
}

Is something like passing additional parameters upon event registration somehow possible? The simplest solution I thought of was to use the delegates return value (changing it to string[]). But that is just hacky and not worth it.

If it is not possible, is there some way I can define += -= myself?

+2  A: 

Why exactly don't you want to use one event per... event ?

What you're trying to do would add an indirection step (which will hurt performance), and more importantly deny you the advantages of compile-time error detection and code analysis (what if your string doesn't match an existing event? wouldn't it be nice to find out about the error at compile-time rather than runtime? What about the "find all references" tool?)

If all of your events are really separate events (which have nothing to do with one another), you should create those events. Creating one single event for all kinds of things would be a bit like creating one big sql table with 255 Columns instead of a true database design.

On the other hand, you may be able to find an abstraction of all those events, and add an argument to the event handler (not to the subscription logic) specifying what sub-event has been called. See IBindingList for an example of this technique. Note the use of an enumeration instead of strings to avoid spelling mistakes.

Could you give us some example (business-wise) of the events you're working on ?

Brann
I'm a 'wrapper' for an UDP-API, where you can send different commands.One can attach a tag to each command you send, which also appears in the reply, so one knows which reply belongs to which command.Every reply has a replyId.Now the registrants are able to listen to either the replyId and/or the tag it has set.If a reply matches the replyId or the tag a registrant is listening to, the event is fired for that specific listener.
This is similar to how Windows Forms manages events. Keep in mind that, with the default implementation, something with fifty events uses in the ballpark of 600 bytes per each instance of the class with the events (8 bytes overhead for a DotNet object plus 4 bytes for the function pointer). Using a list or dictionary reduces that alot.
Snarfblam
A: 

This isn't an answer to your main question, but for ease of use I'd add the "params" keyword to your method, like so:

public void RegisterEvents(dMethod m, params string[] subEvents)

This will let you call the method like this:

RegisterEvents(m, "Bob", "Doug", "Susie");

instead of:

RegisterEvents(m, new string[] { "Bob", "Doug", "Susie" });
MusiGenesis
A: 

The simplest solution I thought of was to use the delegates return value (changing it to string[]).

I dont quite understand what you mean by this. Would the event handler return the events it wants to handle?

I don't think that what you want to do is an option. It may be possible (if you abandon the .Net event system) to use the += syntax by creating a custom class and some implicit conversion operators to produce code something like:

SomePropertyThatIsntARealEvent[new string[] {"event1", "event2"}] += someDelegate
// or even
SomePropertyThatIsntARealEvent["event1"]["event2"] += someDelegate

Note that, if it's even doable, it would be messy and hacky and not really worth it anyways. Also, unfortunately, you can't use params for indexers.

I would recommend that you just stick with the un-pretty way.

Snarfblam
He he, I thought so.I guess I'll be sticking to the registerEvent unregisterEvent way.If there isn't an easy way to do this it just isn't worth it.