Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C# can you set constraints on events?

I want to limit the types that can subscribe to a particular event based on the interface they implement.

I.e. I want an object "Employee" implementing IPerson to subscribe to an event handler but another object "Truck" implementing a totally different interface to be restricted. Out of the box any object implementing the correct method pattern can subscribe.

How do I limit this?

The reason I ask is I am implementing the Observer pattern but trying to do so with C# Events. I have an example working similar to what MSDN has here.

My concern though still is ANY object with ANY structure (so long as it contains the proper delegate method) can be executed when the event fires. So in my example above an Employee could implement the method that makes sense for the objects in my example, but then anyone could go make another class - "truck" in my example above, with any structure (so long as it again implements the method) and tie into the subjects event... This is definitely more of a concern over object usage and good design and maybe I am being nit picky here but this is bothering me.

like image 619
dbobrowski Avatar asked Oct 25 '11 15:10

dbobrowski


People also ask

What does %= mean in C?

%= Modulus AND assignment operator. It takes modulus using two operands and assigns the result to the left operand. C %= A is equivalent to C = C % A.

What is ?: Operator in C?

C operators are one of the features in C which has symbols that can be used to perform mathematical, relational, bitwise, conditional, or logical manipulations. The C programming language has a lot of built-in operators to perform various tasks as per the need of the program.

What does %d do in C?

%d is a format specifier, used in C Language. Now a format specifier is indicated by a % (percentage symbol) before the letter describing it. In simple words, a format specifier tells us the type of data to store and print. Now, %d represents the signed decimal integer.


2 Answers

This is a really bad idea. Please don't do this.

What are you trying to protect against really? Any 'hostile' type can implement the interface (and if they can't see the interface because it's internal to your project, then there's no reason to not make the event internal too), so your blacklist isn't all that well enforced. What's worse, this makes things harder for types on the whitelist - they won't be able delegate listeners to instances of 'close', related types easily. Even the use of a closure (through a lambda / anonymous method) might suddenly break subscriptions - the 'presenting' subscription object might become an instance of a (blacklisted) compiler-generated class.

This is a poor security mechanism and it offers no compile-time safety. It doesn't do a good job of keeping the bad guys out, and makes life difficult for the good guys.

Anyway, this is possible - you will need to use a custom implementation for the event and validate every subscription request.

//Please don't do this.

private EventHandler myEventField = delegate { };

// Add synchronization if required.
public event EventHandler MyEvent
{
   add
   {
      if(value.Target is IPerson)
        myEventField += value;

      else throw new ArgumentException("Subscriber must implement IPerson", "value");
   }

   remove { myEventField -= value; }
}


private void RaiseMyEvent() { myEventField(this, EventArgs.Empty); }
like image 56
Ani Avatar answered Nov 06 '22 05:11

Ani


In C# can you set constraints on events?

Nope.

I want to limit the types that can subscribe to a particular event based on the interface they implement.

Event listeners are instances of delegates of a type compatible with the event type. "Types" are not listeners of events.

I.e. I want an object "Employee" implementing IPerson to subscribe to an event handler but another object "Truck" implementing a totally different interface to be restricted.

An "employee" object doesn't listen to an event in the first place. The only thing that listens to an event is a delegate object.

Are you saying that you only want to accept delegates that are delegates to methods that happen to be instance methods of a particular class? That is a very strange thing to do and I recommend that you not attempt to do so.

It is not possible to prevent that at compile time, but if you are really hell-bent on doing this strange thing, you can do it at runtime.

To do so, as the other answers note, you can create adder and remover accessor methods for the event, and then put a check in the adder that verifies that the receiver of the delegate is of a type you approve of, and throw an exception if it is not.

But again, this sounds like an extraordinarily bad idea. It is up to the listener to decide whether or not they are interested in the event, not up to the event source to vet its listeners. Users have the reasonable expectation that any accessible event can be listened to by any delegate of a compatible type.

Perhaps you can explain why you want to do this strange thing; there might be a better way to achieve your aim.

like image 24
Eric Lippert Avatar answered Nov 06 '22 06:11

Eric Lippert