Event Enhancement - c#

I am trying to figure out away to reduce how many lines our event handlers take. What is the best way to integrate the add {} and remove {}, so I don't have to keep repeating it every time I make a new event.
public delegate void ErrorEventHandler(System.Object sender);
protected ErrorEventHandler ErrorEvent;
public event ErrorEventHandler Error
{
add
{
ErrorEvent = (ErrorEventHandler)System.Delegate.Combine(ErrorEvent, value);
}
remove
{
ErrorEvent = (ErrorEventHandler)System.Delegate.Remove(ErrorEvent, value);
}
}
Thanks to #madreflection the code looks like this now
public delegate void ErrorEventHandler(System.Object sender);
public event ErrorEventHandler Error;
protected virtual void OnError(object sender) => Error?.Invoke(sender);

That is an exceedingly verbose event definition.
The += and -= operators are shorthand for Delegate.Combine and Delegate.Remove, plus you could put the add and remove accessors each on a single line. That would save you some typing and a few lines.
add { ErrorEvent += value; }
Since you're not using a handler collection (e.g. the Events property in System.ComponentModel.Component), there's really no need to implement the add and remove accessors yourself.
The backing field shouldn't be protected. The class that implements the event should control how it's used.
Each event can be reduced to two lines (three if you're defining a delegate type for each event but you shouldn't have to do that):
public event ErrorEventHandler Error;
protected virtual void OnError(object sender) => Error?.Invoke(sender);
The first line is an automatically implemented event. It creates a private backing field for the event and all references to the event within the class use that field directly. It also creates a public event member that can be used by consumers to subscribe to the event. That includes add/remove logic identical to what you have.
The OnError method ("On" + event name) enables derived classes to fire the event without having to use the backing field (since it's private) and encapsulates the null-checking logic. It's protected virtual so that deriving classes can override it and insert logic (such as logging) before calling the base implementation. Thanks to #Markus Safar for pointing out the reason.

Related

c# raise event from another static event in another class

Need help calling event from another class.
I have class with declared event:
public class MxPBaseGridView : GridView
{
public event AddNewItemsToPopUpMenuEventHandler AddNewItemsToPopUpMenu;
...
}
Another class from which i need to call event has methods and "AddNewItemsToPopUpMenuEventHandler " delegate
public delegate void AddNewItemsToPopUpMenuEventHandler(PopupMenuShowingEventArgs e);
public static class GridViewUtils
{
public static void gridView_PopupMenuShowing(object sender, PopupMenuShowingEventArgs e)
{
if (e.MenuType != DevExpress.XtraGrid.Views.Grid.GridMenuType.Row)
{
if (menu != null)
{
if (sender is MxPBaseAdvBandedGridView)
{
MxPBaseAdvBandedGridView currentGrid = sender as MxPBaseAdvBandedGridView;
...
currentGrid.AddNewItemsToPopUpMenu();
if (currentGrid.AddNewItemsToPopUpMenu != null) //there i need to call event
currentGrid.AddNewItemsToPopUpMenu(e); // how you understand it doesn't work
}
so what is the right way to do the same job?
Events in C# are kind of funny things. They're very much like automatic properties, but with a private get method and a public (or whatever access you choose) set method.
Allow me to demonstrate. Let's create a hypothetical class with a hypothetical event.
class SomeObject{
public event EventHandler SomeEvent;
public void DoSomeStuff(){
OnSomeEvent(EventArgs.Empty);
)
protected virtual void OnSomeEvent(EventArgs e){
var handler = SomeEvent;
if(handler != null)
handler(this, e);
}
}
This class follows the typical pattern for a class that exposes an event. It exposes the event publicly, but has a protected virtual "On..." method that, by default, simply calls the event (if it has any subscibers). This protected virtual method not only encapsulates the logic of actually calling the event, but provides a way for derived classes to:
conveniently handle the event with less overhead,
perform some processing before or after all external subscribers receive the event,
call an entirely different event, or
suppress the event altogether.
But what is this "event" object called SomeEvent? In C#, we're familiar with fields, properties, and methods, but what exactly is an event?
Before we get into that, it helps to realize that there are really only two types of class members in C#: fields and methods. Properties and events are more or less just syntactic sugar on top of those.
A property is really either one or two methods, and a name stored in metadata that the C# compiler allows you to use to refer to one of those two methods. That is, when you define a property like this one:
public string SomeProperty{
get{return "I like pie!";}
set{
if(string.Compare(value, "pie", StringComparison.OrdinalIgnoreCase) == 0)
Console.WriteLine("Pie is yummy!");
else Console.WriteLine("\"{0}\" isn't pie!", value ?? "<null>");
}
}
the compiler writes two methods for you:
public string get_SomeProperty(){return "I like pie!";}
public void set_SomeProperty(string value){
if(string.Compare(value, "pie", StringComparison.OrdinalIgnoreCase) == 0)
Console.WriteLine("Pie is yummy!");
else Console.WriteLine("\"{0}\" isn't pie!", value ?? "<null>");
}
I don't mean this obliquely. These two methods literally become part of your compiled class along with a chunk of metadata about the property, which tells the compiler next time which methods to call when the property is read from (get) or written to (set). So when you write code like this:
var foo = someObject.SomeProperty;
someObject.SomeProperty = foo;
The compiler finds the getter and setter methods assigned to SomeProperty, and turns your code into:
string foo = someObject.get_SomeProperty();
someObject.set_SomeProperty(foo);
This is why if you define a class with a public field, but later decide to change it to a property so that you can do something interesting when it is read from or written to, you have to recompile any external assemblies that contain references to this member, because what was a field access instruction needs to become a method call instruction, instead.
Now this property was somewhat abnormal, in that it didn't rely on any backing field. Its getter returned a constant value, and its setter didn't store its value anywhere. To be clear, that's perfectly valid, but most of the time, we define properties more like this:
string someProperty;
public string SomeProperty{get{return someProperty;}set{someProperty = value;}}
This property doesn't do anything other than read and write to a field. It's pretty much the same as a public field named SomeProperty, except that you could add logic to that getter and setter at a later date, without making consumers of your class recompile. But this pattern is so common, that C# 3 added "automatic properties" to achieve the same effect:
public string SomeProperty{get;set;}
The compiler turns this into the same code as we wrote above, except that the backing field has a super secret name that only the compiler knows, so we can only refer to the property in our code, even within the class itself.
Because the backing field is inaccessible to us, while you might have read-only properties like this:
string someProperty;
public string SomeProperty{get{return someProperty;}}
you'll almost never see read-only automatic properties (the compiler lets you write them, but you'll find very little use for them):
public string SomeProperty{get;} // legal, but not very useful unless you always want SomeProperty to be null
Instead, what you'll usually see is this:
public string SomeProperty{get;private set;}
The private access modifier attached to set makes it possible for methods within the class to set the property, but the property still appears read-only outside the class.
"Now what does any of this have to do with events?" you may ask. Well, as a matter of fact, an event is very much like an automatic property. Normally, when you declare an event, the compiler generates a super secret backing field and a pair of methods. Except that the backing field isn't quite as super secret, and the pair of methods aren't "get" and "set", they're "add" and "remove". Let me demonstrate.
When you write an event like this:
public event EventHandler SomeEvent;
what the compiler writes is this:
EventHandler SomeEvent;
public void add_SomeEvent(EventHandler value){
SomeEvent = (EventHandler)Delegate.Combine(SomeEvent, value);
}
public void remove_SomeEvent(EventHandler value){
SomeEvent = (EventHandler)Delegate.Remove(SomeEvent, value);
}
It also adds some metadata glue so that later, when you write code like this:
void Awe_SomeEventHandler(object sender, EventArgs e){}
void SomeMethod(SomeObject Awe){
Awe.SomeEvent += Awe_SomeEventHandler
Awe.SomeEvent -= Awe_SomeEventHandler
}
the compiler rewrites it as (only the interesting lines):
Awe.add_SomeEvent(Awe_SomeEventHandler);
Awe.remove_SomeEvent(Awe_SomeEventHandler);
What's important to take note of here is that the only publicly accessible members related to SomeEvent are those add and remove methods, and those are called when you use the += and -= operators. The backing field, that delegate object named SomeEvent that holds the event's subscribers, is a private field that only members of the declaring class can access.
However, much like the way automatic properties are only a shortcut for writing the backing field and getter and setter by hand, you can explicitly declare your delegate and add and remove methods as well:
internal EventHandler someEvent;
public event EventHandler SomeEvent{
add{someEvent = (EventHandler)Delegate.Combine(someEvent, value);}
remove{someEvent = (EventHandler)Delegate.Remove(someEvent, value);}
}
Then, other classes within your assembly can trigger your event:
var handler = Awe.someEvent;
if(handler != null)
handler(Awe, EventArgs.Empty);
However, it's easier and more idiomatic to define your event the normal (automatic) way, and just expose a "Raise" method:
internal void RaiseSomeEvent(){OnSomeEvent(EventArgs.Empty);}
But now you hopefully understand why you have to do it this way, and what's going on in the background.
You can only invoke an event in the class where you have defined the event. What is common is to use a specific method to fire the event, which you have to add in the class where you define the event. In your case, in the class MxPBaseGridView. Add the following:
public void OnAddNewItemsToPopUpMenu(<eventargstype> e) {
var addNewItemsToPopUpMenu = AddNewItemsToPopUpMenu;
if (addNewItemsToPopUpMenu != null)
addNewItemsToPopUpMenu(this, e);
}
Note: I'm not sure what the eventargs-type is, so I've left it open.
Then you can call this method from your static method.
Note: normally I define the On... methods as private, if necessary as protected. In this case I've defined it public since you need to call it from outside your class.

Additional functionality Events provide over delegate

As I understand an Event is a way for a class to allow clients to give it delegates to methods that should be called when the event occurs. When the event occurs, the delegate(s) given to it by its clients are invoked.
But as demonstrated in following code above said functionality can also be achieved by delegate only i.e. without using delegate.
class Program
{
static void Main(string[] args)
{
ListWithChangedEvent lwce = new ListWithChangedEvent();
lwce.delegateVariable = DelegateTestMethod;
lwce.Add("test");
Console.ReadLine();
}
public static void DelegateTestMethod(object sender, object e)
{
}
}
public delegate void ChangedEventHandler(object sender, object e);
public class ListWithChangedEvent : System.Collections.ArrayList
{
public override int Add(object value)
{
int result = base.Add(value);
if (delegateVariable != null)
delegateVariable(this, "");
return result;
}
public ChangedEventHandler delegateVariable;
}
So, I was wondering what additional functionality does Events provide?
So, I was wondering what additional functionality does Events provide?
Events provide two distinctly different advantages over exposing a public delegate:
You're making the intent very clear. A delegate is typically exposed publically for a very different purpose than an "event" - by using an event, you're very clearly saying "this is something that will get raised at a specific point". Exposing a delegate typically has a different meaning - most often a delegate in a public API is a required input for that API - ie: something that is used directly by the method, not an optional notification mechanism triggered by the method.
Events, technically, are not necessarily just a delegate. An event actually has the option of allowing custom add and remove accessors, which allow you to manually determine what happens when a subscriber subscribes or unsubscribes from the event. For example, many implementations of ICommand.CanExecuteChanged actually don't include their own delegate at all - but silently route to the CommandManager's RequerySuggested event.
Your example allows for a single delegate to be called. The event is a collection of delegates, meaning you can += and -= your heart away (even during event invocation).
event is just the access approach to the handler.
it wont allow you to do myHandler=myFunc;
only using += ( from outer class)
it was made that if another dumb use your code - so he wont destroy your chain by using = so you allow him only += or -=

C# Internal delegate and public Event

I'm currently developing a tiny technical Framework that is independant of any applications. Business code just refers to this Framework.
According this article : http://msdn.microsoft.com/en-us/library/5z57dxz2.aspx (exemple 2), we need to provide a delegate for the custom event.
Problem is, anyone can Invoke my handler (and then raise the event), even in my Business Code and that isn't logical for me, so what is the best way to raise a custom Event with a delegate that is only "internal" and not "public" ?
Thanks for help.
I am not sure if I get it right or not. I think that you feel like if you provide a public Delegate type for your custom event, anyone will be able to Raise that event.
Well, that is not true. Only the class that defines that custom event can raise it. If this is your issue, don't worry.
Not true. It's not allowed to invoke an event outside the class which the event belongs to. Others can only use += and -= operators to your event. Only in the class, you can invoke the event. That is a difference between an event and a normal delegate. That is:
public Data
{
public event EventHandler OnSave
public EventHandler OnLoad;
private void Load()
{
if (OnLoad!=null) OnLoad();
//other operations
}
private void Save()
{
if (OnSave!=null) OnSave();
//other operations
}
}
And outside the class:
Data data = new Data();
data.OnLoad += (s,e) => {};
data.OnSave += (s,e) => {};
data.OnLoad = (s,e)=>{};
//data.OnSave = (s,e)=>{}; //invalid
data.OnLoad();
//data.OnSave(); //invalid
The delegate is just a type declaration describing the "signature" of your event. This has to be public. To actually invoke your event you often implement a method named OnEvent (where you substitute Event with Click or Closed or whatever describes your event). This method should be private (or protected) in your class.
You cannot declare an event using a delegate that is less "visible" than the event.
Problem is, anyone can Invoke my handler (and then raise the event), even in my Business Code
That isn't true. You declare an event as follows:
public event FooEventHandler Foo;
The only thing that external code can do with the event is subscribe to it (+=), or unsubscribe from it (-=). It can't access the actual delegate, which is generated by the compiler as a private field. In other words, this code would be invalid :
SomeClass x = new SomeClass();
x.Foo(x, new FooEventArgs()); // compilation error here
Don't forget that an event is actually a pair of methods (add and remove). The compiler rewrites the event declaration to something along those lines:
private FooEventHandler _foo;
public event FooEventHandler Foo
{
add { _foo += value; }
remove { _foo -= value; }
}
(the generated code is actually a bit more complex, with some locking to ensure thread safety)
As you can see, the _foo field is private, so client code can't access it. Only the event's add and remove accessors are accessible.
One way of doing it:
Instead of public event, create a method that will manually subscribe your desired delegates, and store them in `private List _delegates' field.
Then, from the 'inside', call each of them when you desire.
public class Framework
{
public delegate void Method();
public void AttachEvent(Method M)
{
_methods.Add(M);
}
private List<Method> _methods;
private FireMethods()
{
_methods.Foreach(x=>x.Invoke());
}
}
Or, you can embrace 'by design' feature of the events that they aren't publicly Invoke()-able.
:)

C#: event with explicity add/remove != typical event?

I have declared a generic event handler
public delegate void EventHandler();
to which I have added the extension method 'RaiseEvent':
public static void RaiseEvent(this EventHandler self) {
if (self != null) self.Invoke();
}
When I define the event using the typical syntax
public event EventHandler TypicalEvent;
then I can call use the extension method without problems:
TypicalEvent.RaiseEvent();
But when I define the event with explicit add/remove syntax
private EventHandler _explicitEvent;
public event EventHandler ExplicitEvent {
add { _explicitEvent += value; }
remove { _explicitEvent -= value; }
}
then the extension method does not exist on the event defined with explicit add/remove syntax:
ExplicitEvent.RaiseEvent(); //RaiseEvent() does not exist on the event for some reason
And when I hover over to event to see the reason it says:
The event 'ExplicitEvent' can only
appear on the left hand side of += or
-=
Why should an event defined using the typical syntax be different from an event defined using the explicit add/remove syntax and why extension methods do not work on the latter?
EDIT: I found I can work around it by using the private event handler directly:
_explicitEvent.RaiseEvent();
But I still don't understand why I cannot use the event directly like the event defined using the typical syntax. Maybe someone can enlighten me.
When you create a "field-like" event, like this:
public event EventHandler Foo;
the compiler generates a field and an event. Within the source code of the class which declares the event, any time you refer to Foo the compiler understand that you're referring to the field. However, the field is private, so any time you refer to Foo from other classes, it refers to the event (and therefore the add/remove code).
If you declare your own explicit add/remove code, you don't get an auto-generated field. So, you've only got an event, and you can't raise an event directly in C# - you can only invoke a delegate instance. An event isn't a delegate instance, it's just an add/remove pair.
Now, your code contained this:
public EventHandler TypicalEvent;
This is slightly different still - it wasn't declaring an event at all - it was declaring a public field of the delegate type EventHandler. Anyone can invoke that, because the value is just a delegate instance. It's important to understand the difference between a field and an event. You should never write this kind of code, just as I'm sure you don't normally have public fields of other types such as string and int. Unfortunately it's an easy typo to make, and a relatively hard one to stop. You'd only spot it by noticing that the compiler was allowing you to assign or use the value from another class.
See my article on events and delegates for more information.
Because you can do this (it's non-real-world sample, but it "works"):
private EventHandler _explicitEvent_A;
private EventHandler _explicitEvent_B;
private bool flag;
public event EventHandler ExplicitEvent {
add {
if ( flag = !flag ) { _explicitEvent_A += value; /* or do anything else */ }
else { _explicitEvent_B += value; /* or do anything else */ }
}
remove {
if ( flag = !flag ) { _explicitEvent_A -= value; /* or do anything else */ }
else { _explicitEvent_B -= value; /* or do anything else */ }
}
}
How can the compiler know what it should do with "ExplicitEvent.RaiseEvent();"?
Answer: It can't.
The "ExplicitEvent.RaiseEvent();" is only syntax sugar, which can be predicated only if the event is implicitly implemented.
That's because you're not looking at it right.
The logic is the same as in Properties.
Once you've set the add/remove it's no longer an actual event, but a wrapper to expose the actual event (events can only be triggered from inside the class itself, so you always have access locally to the real event).
private EventHandler _explicitEvent;
public event EventHandler ExplicitEvent {
add { _explicitEvent += value; }
remove { _explicitEvent -= value; }
}
private double seconds;
public double Hours
{
get { return seconds / 3600; }
set { seconds = value * 3600; }
}
In both cases the member with the get/set or add/remove property doesn't really contain any data. You need a "real" private member to contain the actual data.
The properties just allow you program extra logic when exposing the members to outside world.
A good example for WHY you'd want to do it, is to stop extra computation when it's not needed (no one is listening to the event).
For example, lets say the events are triggered by a timer, and we don't want the timer to work if no-one is registered to the event:
private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
private EventHandler _explicitEvent;
public event EventHandler ExplicitEvent
{
add
{
if (_explicitEvent == null) timer.Start();
_explicitEvent += value;
}
remove
{
_explicitEvent -= value;
if (_explicitEvent == null) timer.Stop();
}
}
You'd probably want to lock the add/remove with an object (an afterthought)...
The "plain" declaration for TypicalEvent does some compiler trickery. It creates an event metadata entry, add and remove methods and a backing field. When your code refers to TypicalEvent, the compiler translates it into a reference to the backing field; when external code refers to TypicalEvent (using += and -=), the compiler translates it into a reference to the add or remove method.
The "explicit" declaration bypasses this compiler trickery. You are spelling out the add and remove methods and the backing field: indeed, as TcKs points out, there may not even be a backing field (this is a common reason for using the explicit form: see e.g. events in System.Windows.Forms.Control). Therefore the compiler can no longer quietly translate the reference to TypicalEvent into a reference to the backing field: if you want the backing field, the actual delegate object, you have to reference the backing field directly:
_explicitEvent.RaiseEvent()

C# custom event handlers

If I have a property:
public list<String> names { get; set; }
How can I generate and handle a custom Event for arguments sake called 'onNamesChanged' whenever a name gets added to the list?
A BindingList is likely your best option as it has builtin change tracking and a variety of existing events you can use. Below is an example of exposing a custom event for Add which forwards to the BindingList event.
class Example
{
private BindingList<string> m_names = new BindingList<string>();
public IEnumerable<string> Names { get { return m_names; } }
public event AddingNewEventHandler NamesAdded
{
add { m_names.AddingNew += value; }
remove { m_names.AddingNew -= value; }
}
public void Add(string name)
{
m_names.Add(name);
}
}
You should check out the System.ComponentModel.BindingList, specifically the ListChanged event.
One alternative to BindingList is ObservableCollection - in this case you'd want to subscribe your own event handler to the CollectionChanged event and fire your event depending on the action.
David Mohundro shows one approach; one other option is to inherit from Collection<T> and override the various methods:
class Foo {}
class FooCollection : Collection<Foo>
{
protected override void InsertItem(int index, Foo item)
{
// your code...
base.InsertItem(index, item);
}
protected override void SetItem(int index, Foo item)
{
// your code...
base.SetItem(index, item);
}
// etc
}
Finally, you could create your own list (IList, IList<T>) from first principles - lots of work, little benefit.
A non-orthodox approach might be using an AOP framework such as PostSharp to "weave" a handler before/after the accessor is called, which fires an event.
You create an external class which contains the pre and/or post handling code for when your property is accessed, check if the value of the property changed between pre and post, and raise an event.
Bear in mind that while taking the value for comparison (inside your handler code), you might get into an infinite loop (you call the property accessor, which calls the AOP handler, which calls the accessor and so on), so you might need to reflect into the class containing this property to attain the backing field.

Categories

Resources