I have something like this
class Super{
public event EventHandler MyEvent;
public void Enable(){
MyEvent+=AtEvent;
}
public void Disable(){
MyEvent-=AtEvent;
}
protected void AtEvent(object sender,EventArgs e){
AllThatJazz();
}
}
class Child:Super{
protected new void AtEvent(object sender,EventArgs e){
try{
base.AtEvent(sender,e);
}catch(ObjectDisposedException){}
}
}
class Program{
public static void Main(){
Child c = new Child();
c.Enable();
}
}
c.Enable() attaches the base class's event handler to MyEvent, not the Child's new AtEvent method. Can somebody explain this?
I appreciate suggestions for alternatives, but note that Super is in a separate assembly.
AtEvent is not virtual, it's sealed. You're calling it from a method in the base class, so it is going to be statically bound to that specific implementation of the method. It would need to be virtual (and overridden instead of shadowed) to call the most-derived implementation of that method, or it would need to be called from a reference to the object that was statically typed to Child, which is not currently the case at the place in which you call AtEvent.
Related
I saw some tutorials and I couldn't understand why would they suggest to raise an event from Virtual Protected method, instead of directly, what is the difference?
public delegate void SomethingEventHandler(string s);
public event SomethingEventHandler Something;
public void Main() {
// Raising an event
OnSomething(); // Via method
Something("something"); // Directly
}
protected virtual void OnSomething()
{
Something("something");
}
See "Design Guidelines for Developing Class Libraries", Event Design:
Do use a protected virtual method to raise each event. This is applicable only to non-static events on unsealed classes, not to structures, sealed classes, or static events.
Complying with this guideline allows derived classes to handle a base class event by overriding the protected method. The name of the protected virtual (Overridable in Visual Basic) method should be the same as the event name prefixed with On. For example, the protected virtual method for an event named "TimeChanged" is named "OnTimeChanged".
⚠ Important
Derived classes that override the protected virtual method are not required to call the base class implementation. The base class must continue to work correctly even if its implementation is not called.
I guess that is mainly because of a basic principe called 'Don't Repeat Yourself' (DRY).
For example: you have to raise the NotifyPropertyChanged event when a property's value has changed. You want to do that from 10 properties in your code. You can repeat raising that event from ten methods, or call a method that does that for you. If you have to change something to the event raising, you only have to do that once.
Also, making it protected virtual gives you the opportunity to override that functionality in a derived class.
Also note that for thread-safety, your raising should look like this:
protected virtual void OnSomething()
{
EventHandler d = Something;
if (d != null)
{
d("something");
}
}
Let's say I have 2 classes, classA and classB. Object A (of classA) contains some objects B (of classB). B objects have an event, and object A has subscribed a delegate which is executed when the event (of any of those B objects) is raised.
private void fooEventHandler(object sender, EventArgs e)
{
...
}
After doing something in fooEventHandler (which must be done inside A), I want to signal to the B object which has raised the event the outcome of what I've done in fooEventHandler. So I do the following:
private void fooEventHandler(object sender, EventArgs e)
{
...
if (allOK)
((classB)sender).isOK();
else
((classB) sender).isNotOK();
}
So I'm actually using the sender to call a specific method on objectB after the event rising. I'm doing all this to avoid passing to objectB (in his constructor) some objectA members which from a design point of view shouldn't be in objectB. Is this a reasonable way to handle the issue? Is it common to use (object sender) in this way?
I think you make your A class too coupled with your B class. If all you need A to do after handling the event is call a certain callback - then pass the callback. This way, you could pass in lambda expressions for example, or pass methods of classes related to B or whatever.
So -
private void fooEventHandler(Action p_okCallback, Action p_notOkCallback)
{
...
if (allOK)
p_okCallback();
else
p_notOkCallback();
}
or -
private void fooEventHandler(Action<bool> p_callback)
{
...
p_callback(allOk);
}
If the event is not under your control, you could do like suggested by Helmer and Inherit from EventArgs. But again - I would pass in the callbacks, not the classes themselves.
Another option - if you feel like you'll need multiple methods and feel awkward passing a dozen callbacks around - consider passing an interface with exactly the methods you need.
It's a solution but i think is not the better way do it.
Here is another solution
Step 1 :
- Create an inherit class of a EventArgs and add on it some properties that define the treatment to do in class B
For sample :
public class ClassBEventArgs : EventArgs
{
bool treatmentIsOK = false;
}
Step 2 :
In the same namespace of Class B create a new Delegate Event definition and use it to declare the event
For sample :
namespace ClassBNameSpace
{
public delagate fooEventHandlerDelegate void (object sender, ClassBEventArgs e);
public ClassB
{
public event fooEventHandlerDelegate fooEventHandler;
.........
Step3 :
In ClassB raise the fooEventHandler Event with a ClassBEventArgs object.
In ClassA event handler set the correct value of treatmentIsOK EventArgs. When the event callback from ClassA to ClassB, you can exploit the value of treatmentIsOK propertie
For Sample :
.......
if (this.fooEventHandler != null)
{
ClassBEventArgs customEventArgs = new ClassBEventArgs();
this.fooEventHandler (this,customEventArgs);
if (customEventArgs.treatmentIsOK )
{
this.isOK(); ==> Your code
}
else
{
this.isOK(); ==> Your code
}
}
.......
Why not create your own EventArgs class and put B in there?
Like:
public class ClassBEventArgs : EventArgs
{
public classB classBObject { get; set; }
}
Got the following code
protected virtual void InternalChange(DomainEvent #event)
{
((dynamic) this).Apply(#event);
}
child objects implement the logic to handle events via a number of fields eg
protected Apply ( Message1 message)
{
}
protected Apply ( Message2 message)
{
}
however this gives an error saying its inaccessible. I tried virtual but no luck..
Any ideas ? .. hopefully without reflection like this method. ( eg http://blogs.msdn.com/b/davidebb/archive/2010/01/18/use-c-4-0-dynamic-to-drastically-simplify-your-private-reflection-code.aspx)
More information I can move the InternalChange to the child class but id rather not have the child doing the dispatch.
void Apply(AggregateRootHandlerThatMeetsConventionEvent domainEvent)
{
OnAggregateRootPrivateHandlerThatMeetsConventionCalled = true;
}
void Apply(AggregateRootPrivateHandlerThatMeetsConventionEvent domainEvent)
{
OnAggregateRootPrivateHandlerThatMeetsConventionCalled = true;
}
void Apply(AggregateRootProtectedHandlerThatMeetsConventionEvent domainEvent)
{
OnAggregateRootProtectedHandlerThatMeetsConventionCalled = true;
}
protected override void InternalChange(DomainEvent #event)
{
Apply(((dynamic)#event));
}
Edit for now i'm using this in the child ( and made the parent abstract) which works but its ugly id rather implementers not worry about the dispatch .
protected void Handle(DomainEvent message)
{
Handle ( (dynamic) message);
}
You should define your base class to have either abstract or virtual on the method signature, for instance.
protected abstract void Apply(Message1 message);
Use virtual if you want to define an implementation in your base class that doesn't have to (but can) be overridden in the child class.
In your subclass, you would override it as such:
protected override void Apply(Message1 message)
{
// code here
}
Also, in your example, the method InternalChange is trying to call Apply with an argument of type DomainEvent, however, in both your overloads for Apply, they accept either type of Message1 or Message2. If it did compile, you would get a run time error anyway because the .NET dynamic run time would not be able to find an appropriate method that matches the argument.
As for using dynamic, I think it is unnecessary for the problem at hand.
The logic is sort of... reversed. I don't understand one or two things: what class is calling apply, the base type or the child type? How the discerning of the child class to send the event to happens? Couldn't you render Apply virtual protected and leave it empty in the base class?
I have a base class and a derived class .
The base class has a simple button with a virtual protected button click method.
I am using the ovverride keyword (not using new as i want the buttonclick method in the derived class to override the base class buttonclick method)
However , the code inside the derived class buttonclick method executes twice instead of once
Here is the code example
In the Base Class:
this.ok.Click += new System.EventHandler(this.ok_Click);
protected virtual void ok_Click(object sender, EventArgs e)
{
MessageBox.Show("From the Base class");
}
In the Derived Class:
this.ok.Click += new System.EventHandler(this.ok_Click);
protected override void ok_Click(object sender, EventArgs e)
{
MessageBox.Show("From the Derived class");
}
You haven't said what's actually calling the buttonclick method, but I suspect it's an event handler... and I suspect you're subscribing to it in both the subclass and base class constructors. Don't do that - you only need to subscribe once.
(If that's not the case, please show a short but complete example.)
In my product I need process wide events. For that I used code like this:
public class Global
{
public static event EventHandler<MyEventArgs> Message;
public static void ShowMessage();
}
Now let's say I have a WinForms user interface. In form's code I will subscribe to this event and handle it in some default way (eg. by using System.Windows.Forms.MessageBox.Show() method). Now the question is how do I allow user to create derived form and override my default Message event handler implementation?
Just subscribing to the event for the second time with custom implementation doesn't solve the problem (both event handlers would be executed and potentially two message boxes shown). The options I see are either:
//call OnSubscribeToMessageEvent() from either form's constructor or OnLoad event handler
protected virtual void OnSubscribeToMessageEvent()
{
Global.Message += new EventHandler<MyEventArgs>(Global_Message);
}
private void Global_Message(object sender, MyEventArgs e)
{
//my default implementation
}
or
//subscribe in either form's constructor or OnLoad event handler
protected virtual void Global_Message(object sender, MyEventArgs e)
{
//my default implementation
}
Which version is better and why? Or maybe there are any other options?
I still have some doubts as I have never seen such a design pattern in any .NET library
Yes, you're right to worry about this. These kind of event subscriptions are very fickle, the event source always outlives the subscriber. There's only one class in the framework I know that does this, SystemEvents. The problem is that every subscriber has to very carefully unsubscribe itself when its lifetime ends or the object will stay referenced forever. A memory leak that's very hard to diagnose.
A better pattern here is to use an interface. Let's declare one:
public class MyEventArgs { /* etc.. */ }
public interface IGlobalNotification {
event EventHandler Disposed;
void OnMessage(MyEventArgs arg);
}
Now you can have a form implement the interface:
public partial class Form1 : Form, IGlobalNotification {
public Form1() {
InitializeComponent();
GlobalMessages.Register(this);
}
void IGlobalNotification.OnMessage(MyEventArgs arg) {
// do something
}
}
The Register method registers the form with the GlobalMessages class, the Dispose event ensures that the class can detect that the form is dying:
public static class GlobalMessages {
public static void Register(IGlobalNotification listener) {
listener.Disposed += delegate { listeners.Remove(listener); };
listeners.Add(listener);
}
public static void Notify(MyEventArgs arg) {
foreach (var listener in listeners) listener.OnMessage(arg);
}
private static List<IGlobalNotification> listeners = new List<IGlobalNotification>();
}
Call GlobalMessages.Notify() to get the OnMessage() method to run in all live form instances. The major advantage of this approach is that a client programmer can never screw up.
I would let the derived class override the Global_Message. The subscription to the event is generic and why would you want to implement it in every child again? It also gives you the option to call base.Global_Message(sender, e) in case your child class just wants to add some decoration to it and use the default behaviour otherwise.
I would prefer your second example, as that way, classes that extend your base class only have to override one method and do not have to remove the handler added by the base class from the event.
The key is adding the virtual keyword, so that a derived type can overide the method and the method they created will be called instead.
//subscribe in either form's constructor or OnLoad event handler
protected virtual void Global_Message(object sender, MyEventArgs e)
{
//my default implementation
}
Now that you've added virtual to both, I'd go with the first and override the one that subscribes to the event, if they didn't want the event subscribed to.
Though there is another option, call it #3.
protected EventHandler GlobalMessageEvent = new EventHandler<MyEventArgs>(Global_Message);
protected virtual void OnSubscribeToMessageEvent()
{
// this could be done in the Form_Load() or constructor instead.
Global.Message += GlobalMessageEvent;
}
Then potentially an inherited class could do somewhere: (note the -=)
{
Global.Message -= GlobalMessageEvent;
}