.net default event handler - c#

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;
}

Related

For which purpose the events pattern declares the event firerer method as virtual?

I am trying to understand for which purpose the events pattern decided that the method that fires the event should be declared virtual.
From C#6 in a Nutshell, from Joseph and Ben Albahari, O'Reilley:
Finally, the pattern requires that you write a protected virtual method that fires the
event. The name must match the name of the event, prefixed with the word On, and
then accept a single EventArgs argument:
Below a snippet I created to try to investigate.
I had the impression that the idea was to allow inheriting classes to completely overwrite how the event is handled, out of the box (original class). But the snippet below shows this is not possible, because deriving classes will never be able to invoke the event objects themselves (by the one one of the goals of the constraints imposed by the keyword event on delegates). The event can be invoked only in the containing class.
Now, since the pattern also asks that the method that fires the event simply check if the the event is not null and then call the delegate, with whatever every subscriber asked to do, what is left to be achieved by having the method that fires the event as virtual ? Inheriting classes are obliged to invoke the event the way it is in the broadcaster class, so all that is left for them is to add functionality. But this is exactly what they can achieve by subscribing to the event, in other words, by adding a call to an external function the time the event is fired.
I hope my wording is clear enough.
namespace eventsPatternVirtualEventFirerer
{
internal class Program
{
private static void Main(string[] args)
{
var obj = new X();
obj.ev += Obj_ev;
obj.Start();
}
private static void Obj_ev(object sender, EventArgs e)
{
Console.WriteLine("subscriber code...");
}
}
public class X
{
public event EventHandler<EventArgs> ev;
protected virtual void OnEvent(EventArgs e)
{
Console.WriteLine("original implementation...");
ev?.Invoke(this, e);
}
public void Start()
{
OnEvent(EventArgs.Empty);
}
}
public class X2 : X
{
public X2()
{
}
protected override void OnEvent(EventArgs e)
{
Console.WriteLine("inheriting class implementation overwrite...");
//compilation error - "the event 'X.ev' can only appear on the left hand side of += or -= (except when used from within the type 'X')"
ev?.Invoke(this, e);
}
}
}
I think the purpose is to allow derived classes to do something before/after the event is fired
public class X2 : X
{
public X2()
{
}
protected override void OnEvent(EventArgs e)
{
// Do something before the event
base.OnEvent(e);
// Do something after the event
}
}
There are a few things you can add/change in a derived class
Add a OnBeforeEvent / OnAfterEvent addition.
Choose not to broadcast the event (by conditionally not calling base.OnEvent(e)).
Vary the event args in some way.
Additionally, If you think about the way something like a page model works, it typically fires a Load event to notify when the page is loaded. Without a protected OnLoad method, derived classes would have to subscribe to it's own Load event to perform some action on load
public class MyPage : Page
{
protected override void OnLoad(EventArgs e)
{
// do something when the page is loaded
base.OnLoad(e);
}
}
versus:
public class MyPage : Page
{
public MyPage() : base()
{
this.Load += (sender,e) => {
// bleugh - subscribing to my own events
}
}
}
A good example might be the Paint event in Windows Forms.
// in MyButton : BaseButton : Control
void override OnPaint(object s, PaintEveargs e)
{
base.OnPaint(s, e); // Control: Draw background, BaseButton: draw border
// draw my own stuff
}
A button has several layers of base class, each drawing on top of each other.

Implementing event in base of a object

Ive implemented an event in a object like this:
public class BaseObject
{
public delegate void NavigateHandler(object sender, EventArgs e);
public virtual event NavigateHandler Navigate;
A child og that base tries to invoke it:
public class ChildObject : BaseObject
{
private void DoNavigate()
{
Navigate(null, null);
This part above is broken, VS2012 tells me that I cant use Navigate in that manner.
However, it works fine to "hook" on that event if I instansiate a object of ChildObject:
ChildObject obj = new ChildObject();
obj.Navigate += foo_Navigate;
Where did I go wrong? I want to trigger that navigate event in the DoNavigate method.
You are only allow to invoke events from within the class that defines it.
If you want to allow sub-classes to fire the event then create a protected method (by convention it would be called OnNavigate) that fires the event and that can be accessed from implementing classes.

Raise an event of a class from a different class in C#

I have a class, EventContainer.cs, which contains an event, say:
public event EventHandler AfterSearch;
I have another class, EventRaiser.cs. How do I raise (and not handle) the above said event from this class?
The raised event will in turn call the handler of the event in the EventContainer class. Something like this (this is obviously not correct):
EventContainer obj = new EventContainer();
RaiseEvent(obj.AfterSearch);
This is not possible, Events can only be risen from inside the class. If you could do that, it would defeat the purpose of events (being able to rise status changes from inside the class). I think you are misunderstanding the function of events - an event is defined inside a class and others can subscribe to it by doing
obj.AfterSearch += handler; (where handler is a method according to the signature of AfterSearch). One is able to subscribe to the event from the outside just fine, but it can only be risen from inside the class defining it.
It is POSSIBLE, but using clever hack.
Inspired by http://netpl.blogspot.com/2010/10/is-net-type-safe.html
If you don't believe, try this code.
using System;
using System.Runtime.InteropServices;
namespace Overlapping
{
[StructLayout(LayoutKind.Explicit)]
public class OverlapEvents
{
[FieldOffset(0)]
public Foo Source;
[FieldOffset(0)]
public OtherFoo Target;
}
public class Foo
{
public event EventHandler Clicked;
public override string ToString()
{
return "Hello Foo";
}
public void Click()
{
InvokeClicked(EventArgs.Empty);
}
private void InvokeClicked(EventArgs e)
{
var handler = Clicked;
if (handler != null)
handler(this, e);
}
}
public class OtherFoo
{
public event EventHandler Clicked;
public override string ToString()
{
return "Hello OtherFoo";
}
public void Click2()
{
InvokeClicked(EventArgs.Empty);
}
private void InvokeClicked(EventArgs e)
{
var handler = Clicked;
if (handler != null)
handler(this, e);
}
public void Clean()
{
Clicked = null;
}
}
class Test
{
public static void Test3()
{
var a = new Foo();
a.Clicked += AClicked;
a.Click();
var o = new OverlapEvents { Source = a };
o.Target.Click2();
o.Target.Clean();
o.Target.Click2();
a.Click();
}
static void AClicked(object sender, EventArgs e)
{
Console.WriteLine(sender.ToString());
}
}
}
You can write a public method on the class you want the event to fire from and fire the event when it is called. You can then call this method from whatever user of your class.
Of course, this ruins encapsulation and is bad design.
It looks like you're using the Delegate pattern. In this case, the AfterSearch event should be defined on the EventRaiser class, and the EventContainer class should consume the event:
In EventRaiser.cs
public event EventHandler BeforeSearch;
public event EventHandler AfterSearch;
public void ExecuteSearch(...)
{
if (this.BeforeSearch != null)
this.BeforeSearch();
// Do search
if (this.AfterSearch != null)
this.AfterSearch();
}
In EventContainer.cs
public EventContainer(...)
{
EventRaiser er = new EventRaiser();
er.AfterSearch += this.OnAfterSearch;
}
public void OnAfterSearch()
{
// Handle AfterSearch event
}
I stumbled across this problem as well, because i was experimenting with calling PropertyChanged events from outside. So you dont have to implement everything in every class. The solution from halorty wouldn't work using interfaces.
I found a solution working using heavy reflection. It is surely slow and is breaking the principle that events should only be called from inside a class. But it is interesting to find a generic solution to this problem....
It works because every event is a list of invocation methods being called.
So we can get the invocation list and call every listener attached to that event by our own.
Here you go....
class Program
{
static void Main(string[] args)
{
var instance = new TestPropertyChanged();
instance.PropertyChanged += PropertyChanged;
instance.RaiseEvent(nameof(INotifyPropertyChanged.PropertyChanged), new PropertyChangedEventArgs("Hi There from anywhere"));
Console.ReadLine();
}
private static void PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Console.WriteLine(e.PropertyName);
}
}
public static class PropertyRaiser
{
private static readonly BindingFlags staticFlags = BindingFlags.Instance | BindingFlags.NonPublic;
public static void RaiseEvent(this object instance, string eventName, EventArgs e)
{
var type = instance.GetType();
var eventField = type.GetField(eventName, staticFlags);
if (eventField == null)
throw new Exception($"Event with name {eventName} could not be found.");
var multicastDelegate = eventField.GetValue(instance) as MulticastDelegate;
if (multicastDelegate == null)
return;
var invocationList = multicastDelegate.GetInvocationList();
foreach (var invocationMethod in invocationList)
invocationMethod.DynamicInvoke(new[] {instance, e});
}
}
public class TestPropertyChanged : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
}
There is good way to do this. Every event in C# has a delegate that specifies the sign of methods for that event. Define a field in your external class with type of your event delegate. get the the reference of that field in the constructor of external class and save it. In main class of your event, send the reference of event for delegate of external class. Now you can easily call the delegate in your external class.
public delegate void MyEventHandler(object Sender, EventArgs Args);
public class MyMain
{
public event MyEventHandler MyEvent;
...
new MyExternal(this.MyEvent);
...
}
public MyExternal
{
private MyEventHandler MyEvent;
public MyExternal(MyEventHandler MyEvent)
{
this.MyEvent = MyEvent;
}
...
this.MyEvent(..., ...);
...
}
Agree with Femaref -- and note this is an important difference between delegates and events (see for example this blog entry for an good discussion of this and other differences).
Depending on what you want to achieve, you might be better off with a delegate.
Not a good programming but if you want to do that any way you can do something like this
class Program
{
static void Main(string[] args)
{
Extension ext = new Extension();
ext.MyEvent += ext_MyEvent;
ext.Dosomething();
}
static void ext_MyEvent(int num)
{
Console.WriteLine(num);
}
}
public class Extension
{
public delegate void MyEventHandler(int num);
public event MyEventHandler MyEvent;
public void Dosomething()
{
int no = 0;
while(true){
if(MyEvent!=null){
MyEvent(++no);
}
}
}
}
I had a similar confusion and honestly find the answers here to be confusing. Although a couple hinted at solutions that I would later find would work.
My solution was to hit the books and become more familiar with delegates and event handlers.
Although I've used both for many years, I was never intimately familiar with them.
http://www.codeproject.com/Articles/20550/C-Event-Implementation-Fundamentals-Best-Practices
gives the best explanation of both delegates and event handlers that I've ever read and clearly explains that a class can be a publisher of events and have other classes consume them.
This article: http://www.codeproject.com/Articles/12285/Implementing-an-event-which-supports-only-a-single discusses how to single-cast events to only one handler since delegates are multicast by definition . A delegate inherits system.MulticastDelegate most including the system delegates are Multicast.
I found that multicast meant that any event handler with the same signature would receive the raised event. Multicast behavior has caused me some sleepless nights as I stepped through code and saw my event seemingly erroneously being sent to handlers that I had no intention of getting this event. Both articles explains this behavior.
The second article shows you one way, and the first article shows you another, by making the delegate and the signature tightly typed.
I personally believe strong typing prevents stupid bugs that can be a pain to find. So I'd vote for the first article, even though I got the second article code working. I was just curious. :-)
I also got curious if I could get #2 articles code to behave like how I interpreted the original question above. Regardless of your chosen approach or if I'm also misinterpreting the original question, my real message is that I still think you would benefit from reading the first article as I did, especially if the questions or answers on this page leave you confused. If you are having multicast nightmares and need a quick solution then article 2 may help you.
I started playing with the second article's eventRaiser class. I made a simple windows form project.
I added the second articles class EventRaiser.cs to my project.
In the Main form's code, I defined a reference to that EventRaiser class at the top as
private EventRaiser eventRaiser = new EventRaiser();
I added a method in the main form code that I wanted to be called when the event was fired
protected void MainResponse( object sender, EventArgs eArgs )
{
MessageBox.Show("got to MainResponse");
}
then in the main form's constructor I added the event assignment:
eventRaiser.OnRaiseEvent += new EventHandler(MainResponse);`
I then created a class that would be instantiated by my main form called "SimpleClass" for lack of creative ingenuity at the moment.
Then I added a button and in the button's click event
I instantiated the SimpleClass code I wanted to raise an event from:
private void button1_Click( object sender, EventArgs e )
{
SimpleClass sc = new SimpleClass(eventRaiser);
}
Note the instance of "eventRaiser" that I passed to SimpleClass.cs. That was defined and instantiated earlier in the Main form code.
In the SimpleClass:
using System.Windows.Forms;
using SinglecastEvent; // see SingleCastEvent Project for info or http://www.codeproject.com/Articles/12285/Implementing-an-event-which-supports-only-a-single
namespace GenericTest
{
public class SimpleClass
{
private EventRaiser eventRaiser = new EventRaiser();
public SimpleClass( EventRaiser ev )
{
eventRaiser = ev;
simpleMethod();
}
private void simpleMethod()
{
MessageBox.Show("in FileWatcher.simple() about to raise the event");
eventRaiser.RaiseEvent();
}
}
}
The only point to the private method I called SimpleMethod was to verify that a privately scoped method could still raise the event, not that I doubted it, but I like to be positive.
I ran the project and this resulted in raising the event from the "simpleMethod" of the "SimpleClass" up to the main form and going to the expected correct method called MainResponse proving that one class can indeed raise an event that is consumed by a different class.
Yes the event has to be raised from within the class that needs it's change broadcast to other classes that care. Receiving classes can be one class or many many classes depending on how strongly typed you defined them or by making them single cast as in 2nd article.
Hope this helps and not muddy the water. Personally I've got a lot of delegates and events to clean up! Multicast demons begone!
The raising class has to get a fresh copy of the EventHandler.
One possible solution below.
using System;
namespace ConsoleApplication1
{
class Program
{
class HasEvent
{
public event EventHandler OnEnvent;
EventInvoker myInvoker;
public HasEvent()
{
myInvoker = new EventInvoker(this, () => OnEnvent);
}
public void MyInvokerRaising() {
myInvoker.Raise();
}
}
class EventInvoker
{
private Func<EventHandler> GetEventHandler;
private object sender;
public EventInvoker(object sender, Func<EventHandler> GetEventHandler)
{
this.sender = sender;
this.GetEventHandler = GetEventHandler;
}
public void Raise()
{
if(null != GetEventHandler())
{
GetEventHandler()(sender, new EventArgs());
}
}
}
static void Main(string[] args)
{
HasEvent h = new HasEvent();
h.OnEnvent += H_OnEnvent;
h.MyInvokerRaising();
}
private static void H_OnEnvent(object sender, EventArgs e)
{
Console.WriteLine("FIRED");
}
}
}
Use public EventHandler AfterSearch;
not
public event EventHandler AfterSearch;
Use a Delegate (an Action or Func) instead of an event. An event is essentially a delegate that can only be triggered from within the class.
I took a slightly different approach in solving this problem. My solution consisted of a winform front end, a main Class Library (DLL) and within that dll, a secondary working class:
WinForm
|------> PickGen Library
|---------> Allocations class
What I decided to do is to create events in the main dll (PickGen) that the Allocations class could call, then those event methods would called the events within the UI.
So, allocations raises an event in PickGen which takes the parameter values and raises the event in the form. From a code standpoint, this is in the lowest class:
public delegate void AllocationService_RaiseAllocLog(string orderNumber, string message, bool logToDatabase);
public delegate void AllocationService_RaiseAllocErrorLog(string orderNumber, string message, bool logToDatabase);
public class AllocationService { ...
public event AllocationService_RaiseAllocLog RaiseAllocLog;
public event AllocationService_RaiseAllocErrorLog RaiseAllocErrorLog;
then later in the subclass code:
RaiseAllocErrorLog(SOHNUM_0, ShipmentGenerated + ": Allocated line QTY was: " + allocatedline.QTY_0 + ", Delivered was: " + QTY_0 + ". Problem batch.", false);
In the main DLL Class library I have these two event methods:
private void PickGenLibrary_RaiseAllocLog(string orderNumber, string message, bool updateDB)
{
RaiseLog(orderNumber, message, false);
}
private void PickGenLibrary_RaiseAllocErrorLog(string orderNumber, string message, bool updateDB)
{
RaiseErrorLog(orderNumber, message, false);
}
and I make the connection here when I create the allocation object:
AllocationService allsvc = new AllocationService(PickResult);
allsvc.RaiseAllocLog += new AllocationService_RaiseAllocLog(PickGenLibrary_RaiseAllocLog);
allsvc.RaiseAllocErrorLog += new AllocationService_RaiseAllocErrorLog(PickGenLibrary_RaiseAllocErrorLog);
and I also then have delegates that are set up to tie the main class with the winform code:
public delegate void JPPAPickGenLibrary_RaiseLog(string orderNumber, string message, bool logToDatabase);
public delegate void JPPAPickGenLibrary_RaiseErrorLog(string orderNumber, string message, bool logToDatabase);
It may not be the most elegant way to do it, but in the end, it does work and without being too obscure.
A nested class with an instance of the outer class provided in the constructor can access even private members of the outer class. As explained more here: stackoverflow question on inner classes.
This includes the ability to raise events in the outer class. This EventRaisers class could be internal, or otherwise controlled somehow, because it could technically otherwise be created by any script with a reference to the outer class instance.
Very simple example. i like to do it this way using EventHandler.
class Program
{
static void Main(string[] args)
{
MyExtension ext = new MyExtension();
ext.MyEvent += ext_MyEvent;
ext.Dosomething();
Console.ReadLine();
}
static void ext_MyEvent(object sender, int num)
{
Console.WriteLine("Event fired.... "+num);
}
}
public class MyExtension
{
public event EventHandler<int> MyEvent;
public void Dosomething()
{
int no = 1;
if (MyEvent != null)
MyEvent(this, ++no);
}
}
}

Explain code for custom event in user control

Someone gave me this code that works great. But I would really like to understand what is happening inside it. Could somebody explain please? What is the meaning of each part of the code? The code is inside a custom control which has two labels inside a panel.
Also I've seen some custom control events that use add/remove syntax, what is that for? What is the difference with what is happening here?
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public event EventHandler MyCustomClickEvent;
protected virtual void OnMyCustomClickEvent(EventArgs e)
{
// Here, you use the "this" so it's your own control. You can also
// customize the EventArgs to pass something you'd like.
if (MyCustomClickEvent != null)
MyCustomClickEvent(this, e);
}
private void label1_Click(object sender, EventArgs e)
{
OnMyCustomClickEvent(EventArgs.Empty);
}
}
See my comments below. Also for a more detailed event I blogged on this concept a while back where I go into more detail on the entire process.
public partial class UserControl1 : UserControl
{
//This is the standard constructor of a user control
public UserControl1()
{
InitializeComponent();
}
//This defines an event called "MyCustomClickEvent", which is a generic
//event handler. (EventHander is a delegate definition that defines the contract
//of what information will be shared by the event. In this case a single parameter
//of an EventArgs object.
public event EventHandler MyCustomClickEvent;
//This method is used to raise the event, when the event should be raised,
//this method will check to see if there are any subscribers, if there are,
//it raises the event
protected virtual void OnMyCustomClickEvent(EventArgs e)
{
// Here, you use the "this" so it's your own control. You can also
// customize the EventArgs to pass something you'd like.
if (MyCustomClickEvent != null)
MyCustomClickEvent(this, e);
}
private void label1_Click(object sender, EventArgs e)
{
OnMyCustomClickEvent(EventArgs.Empty);
}
}
I'd recommend reading up on Events for C# on MSDN. This is covered in detail.
Basically, MyCustomClickEvent is an event. The OnMyCustomClickEvent method is used to raise the event, but is being done in a way that subclasses can also raise this event if required.
When you click on "label1", the OnMyCustomClickEvent method runs, which raises the event. Any delegates subscribed to the event will execute at that point.
You mentioned seeing the add/remove syntax for events in some custom control examples. Most likely those examples are using the UserControl class' Events property to store event handlers, such as in the following example:
public event EventHandler MyEvent
{
add
{
Events.AddHandler("MyEvent", value);
}
remove
{
Events.RemoveHandler("MyEvent", value);
}
}
The idea there is that usually a consumer of a control is not going to want to handle every single event that the control exposes. If each event is defined as a "field" event (as in your example), then each event will take up a chunk of memory even if there are no subscribers for that event. When you have a complex page constructed of hundreds of controls, each of which may have dozens of events, the memory consumption for unused events is not insignificant.
This is why the System.ComponentModel.Component class (the base class of the System.Windows.Forms.Control class) has an Events property, which is basically a dictionary to store event handler delegates. This way each event is implemented more like a property than a field. The add/remove handlers for each event store or remove delegates from the Events dictionary. If an event is not used, then there just isn't an entry in the Events dictionary for it, and no additional memory is consumed for that event. It's a trade-off of doing slightly more work (having to look up the event handler) to save slightly more memory.
EDIT: fixed my answer to pertain to Windows Forms, rather than ASP.NET, although the concepts are the same.
Concerning the add/remove, this is a "manual" implementation of events. The following two snippets do the same thing.
Automatic implementation:
public event EventHandler MyEvent;
Manual implementation:
private EventHandler _myEvent;
public event EventHandler MyEvent
{
add { _myEvent += value; }
remove { _myEvent -= value; }
}
This is exactly the same idea as automatic properties where:
public string Property { get; set; };
Does exactly the same as:
private string _property;
public string Property
{
get { return _property; }
set { _property = value; }
}
The difference between these snippets is that with the manual implementations, you get more control. Examples are:
Implement logic in the add/get and remove/set;
Get access to the fields which allows you to set e.g. [NonSerializable];
Put the values in e.g. a Dictionary.
The Form class e.g. does the latter to keep the number of fields in the Form class down.

How to "unbind" an event handler attached to an event in the base class when I'm in a derived class?

I had once a situation where I had to override the event handler in some derived class of mine. I could not unfortunately just "override" it since the implementation logic was bound strictly to that particular method implementation in the base class.
My natural idea was to first "unbind" the original event handler from the event and then to bind my own brand-new method. So I tried to use the "-=" operator like:
myObject.SomeEvent -= new EventHandler (BaseClass.SomeEventHandler)
at which point the compiler complainer that it had no access to the private method SomeEventHandler. Since the base class was a part of the library I did not really want to modify its implementation (though simply as it seems by just turning "private" into "protected");
It's so simple to attach an event handler to an event. Why is it so difficult to get rid of one?
Why I wanted it? Because the base implementation was casing some problems (just did not handle our particular case) so I wanted to redefine it. But even after I attached my event handler the base implementation was getting executed anyway. Since it was doing some kind of Redirect, my own implementation was never going to run since the request processing was being broken at server after redirect.
Is there anyway to get rid of an event handler in a base class from a library without modifying its implementation?
It would be just as easy to get rid of the handler if your code can officially see the handler. If absolutely necessary, it is possible to unsubscribe using reflection to get hold of the delegate, but this is messy. It would be a lot cleaner and safer to either a: avoid the requirement, or b: change the code to make the handler protected.
Reflection approach (use at own risk); uncomment the block in the Bar.ctor() to see the change.
using System;
class Foo
{
public event EventHandler SomeEvent;
public Foo()
{
SomeEvent += SecretHandler; // a bad idea, anyway
//(self-subscribed events....)
}
protected virtual void OnSomeEvent()
{
EventHandler handler = SomeEvent;
if (handler != null) handler(this, EventArgs.Empty);
}
private void SecretHandler(object sender, EventArgs args)
{
Console.WriteLine("suscribed");
}
}
class Bar : Foo
{
public Bar()
{
/*
MethodInfo method = typeof(Foo).GetMethod("SecretHandler",
BindingFlags.NonPublic | BindingFlags.Instance);
EventHandler handler = (EventHandler)Delegate.CreateDelegate(
typeof(EventHandler), this, method);
SomeEvent -= handler;
*/
}
public void Test()
{
OnSomeEvent();
}
}
static class Program
{
static void Main()
{
Bar bar = new Bar();
bar.Test();
}
}

Categories