Why to use events somewhere where method is enough? - c#

I read some events tutorial and just do not get what is the benefit in simple code like this..method should be used the same way:
class Bulb
{ public delegate void handler();
public event handler Glowing;
...
Glowing+=SomeMethod;
private void TurnOn
{
Glowing();
}
private void SomeMethod
{
}
}

Simply Events allow others using your code to perform some custom Implementation they want when that Event occurs (when Bulb is Glowing).
Simply calling your method won't tell anybody that something has happened.
Events are very basic Element of any Event Driven Programming
If your program doesn't need to tell about an event you don't need to implement such Functionality. However having such functionality has benefits.
For Example when using a List Class you dont know when an Item got added to it (if at some point some other code does that) but in a ObservableCollection you get notifications when Items are Added or Removed.
An event is a message sent by an object to signal the occurrence of an action. The action could be caused by user interaction, such as a mouse click, or it could be triggered by some other program logic.

The idea is that a different class which can hold Three different Bulbs can get notified by the event (if it implements a handler) that the light has been turned on and is Glowing.
So the benefit does not reside in the simply class but in what ever classes/objects are going to be holding/using instances of the Bulb class.
Hope that made some sense :)

Events over methods become handy when you have a class dependency that needs to know or be notified about a stateful change:
public class Lamp
{
Bulb inThelamp = new Bulb();
inTheLamp.Glowing += myLampMethod;
// If these arguments have been defined for this event that is
public void myLampMethod(object sender, EventArgs e)
{
// Code to react to the light suddenly being on
}
}
This allows the Lamp class to recognize that something has turned the bulb on. In many cases it will be through some action in the Lamp (click, pushknob, etc). But in some cases it could be an external class that calls a public Bulb property directly without using the Lamp itself (such is if(PowerCompany.BillsPaid) Lamp.BulbInTheLamp.TurnedOn();). This is all assuming that the modifiers are set to allow this kind of access.
The point is that it allows notification of an occurrence rather than requiring that a particular method be called manually each time you want an action to occur.

Related

wrapping around an event inside another class c#

I am writing a wrapper around a class that extends some parts of a 3th party class. It adds some functionality that was missing. And by keeping it a class I can use it in multiple projects.
However I wonder how should I wrap around something that raises an event.
So that I can extend those events as well but still be able to raise an event for apps that use my extended class. So it acts a bit like a passtrough with added functionality. Let me clarify this with a bit of code
So MyExtend class has this code fragment in its constructor
thirdpartyClass theirclass += new thirdpartyclass()
thirdpartyClass.init()
theirclass.EventX = += MyWrapper_Method
Then the wrapper for the event inside MyExtend class look like
Public Void MyWrappedEvent_method()
{
messagebox("logged it") //it actually logs to a database but i keep it short here
}
Now some other program in the future should be able to use MyExtend class.
And be able to do other things besides logging it, when a certain events (ea MyWrappedEvent) happens so that i could write
Using MyExtend;
//somwhere in main
MyExtend HasExtended = new MyExtend();
HasExtended.MyWrapper += NewFutureRoutine()
//...
// ..
public void NewFutureRoutine()
{
//when i call this event i wont need to care about logging thats allready in it
// so i could focus on other tasks ea:
Arduino.Controller(setHardwarePin,high);
}
In order to let your MyExtend class handle the events, you will need to catch the desired event in your class, then fire another event and subscribe to it.
I would recommend to read and follow the following links/instructions:
Raising an Event
How to: Raise and Consume Events
How to manually invoke an event?

Forwarding events to selected instance

Is there a good strategy to exchange the receiver of multiple events (let's say an object instance A) during runtime to another instance B (or multiple instances)? For example think of a menu bar with a bunch of operations that can be performed on the currently selected of multiple objects.
Now one option would be to connect all object's handlers to the click events and let the handlers filter out the relevant calls (by checking if the current instance is selected) or registering/unregistering the events on selection.
Another one would be to register the events to an object functioning as proxy like this (rough code):
class ClickEventProxy
{
private static ClickEventProxy selectedInstance; // <-- changend on selection
public event EventHandler SomeEventToForward;
public static void RaiseSomeEventToForward(object sender, EventArgs e)
{
if (selectedInstance.ClickedAddNewFrame != null)
selectedInstance.ClickedAddNewFrame(sender, e);
}
...
}
The sender-site would look like SomeSource.Click += ClickEventProxy.RaiseSomeEventToForward; and all receivers would subscribe to their instance of the proxy.
However handling the instances (e.g. by a global <object, proxy instance> dictionary) is a bit unconvenient and the whole thing looks a bit clumsy. So my question: Is there a more programmatic way to do so? Or is it itself bad practice proxying events by introducing another step and one should rather remove and readd the handlers? (Maybe this could be made better by using custom events and altering the invocation list...)

How do I implement this kind of event listener design?

I am new to C# so this is probably me just not understanding something fundamental or missing out on some feature of the language. I've searched online but all the examples I seem to find have everything all in one class (in other words, they define the event as well as the method that executes when the event is triggered), which is not what I want.
For my scenario I'd like to define an interface of listener methods that can accept some custom parameters (this would be my own EventArgs right?) that provide instructions. Lets pretend its for a car, so I have methods named:
Start(MyCustomParameters par)
Accelerate(MyCustomParameters par)
Decelerate(MyCustomParameters par)
and then I want to be able to create classes that provide the actual implementation of these methods.
completely separate from all this, I have a single class that executes periodically based on an external process and I want it to be responsible for triggering these events (when the car starts and accelerates etc).
That's the basics of what I'm trying to get working but no luck so far. Also, one follow-up question. If my listener-implementation class needs to maintain any kind of state from a given call, how best to do that (e.g. say that when Accelerate is called it wants to be able to return the speed that it accelearted to back to the invoker of the event - e.g. 80 kph)
hope you can help SO, thank you very much
here is a simple example of event/listener in c# :
//your custom parameters class
public class MyCustomParameters
{
//whatever you want here...
}
//the event trigger
public class EventTrigger
{
//declaration of the delegate type
public delegate void AccelerationDelegate(MyCustomParameters parameters);
//declaration of the event
public event AccelerationDelegate Accelerate;
//the method you call to trigger the event
private void OnAccelerate(MyCustomParameters parameters)
{
//actual triggering of the events
if (Accelerate != null)
Accelerate(parameters);
}
}
//the listener
public class Listener
{
public Listener(EventTrigger trigger)
{
//the long way to subscribe to the event (to understand you create a delegate)
trigger.Accelerate += new EventTrigger.AccelerationDelegate(trigger_Accelerate);
//a shorter way to subscribe to the event which is equivalent to the statement above
trigger.Accelerate += trigger_Accelerate;
}
void trigger_Accelerate(MyCustomParameters parameters)
{
//implement event handling here
}
}
I hope it helps.

Why public event cannot be invoked outside directly?

Consider we have a class with event declared:
public class FooBar
{
public event EventHandler FooBarEvent;
}
Despite of "publicness" of the event, we cannot call FooBarEvent.Invoke from outside.
This is overcame by modyfing a class with the following approach:
public class FooBar
{
public event EventHandler FooBarEvent;
public void RaiseFooBarEvent(object sender, EventArgs eventArguments)
{
FooBarEvent.Invoke(sender, eventArguments);
}
}
Why accessing public events outside is limited by adding and removing listeners only?
Defining a public event merely gives consumers the ability to subscribe and unsubscribe from it. The ability to raise the event is limited to the type hierarchy which declares the event.
Allowing all subscribers to also be able to raise the event would be a bit chaotic. Imagine for example I had a TextBox class which had a Focused event. If any old consumer could raise the event then the Focused event could easily fire when the TextBox class wasn't actually focused. This would make it nearly impossible to maintain any type of invariant during an event.
Personally I think this is done to properly convey the design principles behind the whole events architecture.
The purpose of an event is to notify a listener of said event occurring in a given object.
What's the point of raising events of classes that don't belong to you?
That's what events are for. If you want to invoke it publicly you probably need delegates not events
Events gives encapsulation,
It prevents other classes from assigning anything to it
It prevents passing it as a parameter to methods
It prevents assigning it to any variable
It prevents calling it from another classes (not even derived classes have access to it)
etc
public accessibility tells that it can be subscribed from anywhere, not invoked from anywhere.
the answer to your question is
An event in C# is a way for a class to provide notifications to clients of that class when some interesting thing happens to an object.
Invoking the event from outside doesn't makes sense therefore it is not allowed.
I think you should change your perspective on how events work. Other classes shouldn't "own" the event and trigger it. Classes which "listen" to the event by "subscribing" to it and do a certain action when this event occurs.
That's the way the language is defined - an event can only be fired by the owning class. If you must fire it from a different class, have the owning class define a public method that will fire the event:
public FireFooBarEvent (object sender, EventArgs args)
{
if(FooBarEvent != null)
FooBarEvent(sender, args);
}
And call this method from any class.

Mixing enums with event classes in an event aggregator

I attempted to implement my own simple event aggregator recently. I got a lot of inspiration from the event aggregator article on MSDN. There is one thing that I notice about the event aggregator on MSDN is the events are actually classes on their own. This isn't really a bad thing at all. However, I just find it awkward to always create a new empty class for every single little event.
The reason I find it awkward is because of the need to create a class for every single granular event. A mouse click event, for instance, would have double_click, single_click, left_click, right_click, etc. And all of these are going to have a class of its own. It gets messy after a while.
So in my own implementation, I thought I could make it in such a way where the ClickEvent is a class, but all the granular events related to the Click event would then be "types" of the ClickEvent. In this case, the "types" are enum. The usage would look something like this:
//Publisher
eventAggregator.GetEvent<ClickEvent>.Publish(ClickEventType.Double_Click, eventArgs);
//Subscriber
eventAggregator.GetEvent<ClickEvent>.Subscribe(ClickEventType.Double_Click, handlerMethod);
However, I'm not sure if this implementation defeats the whole purpose of having a strongly typed event? Now, it seems like the ClickEvent is merely a container for the different event enum types.
Yes it does (seem like a container that is) - your handler will fire regardless of the click type and there will be some code required in the handler to determine the type of click, which makes things a little messier.
If your issue is mostly the organisation of the files/classes and keeping the code tidy, why not just create the click events as nested classes within a main click class
e.g.
public static class ClickEvents // Prevent instantiation
{
public class SingleLeft { }
public class SingleRight { }
public class DoubleLeft { }
public class DoubleRight { }
// Are there any more click events possible?!
}
eventAggregator.GetEvent<ClickEvents.SingleLeft>.Publish();
Aside from that, it's the uniqueness of the type that determines the event signature, and therefore multiple types are required to satisfy this particular implementation
At least the above keeps your handler code clean
void HandleLeftClick()
{
}
vs
void HandleClick(ClickArgs e)
{
if(e.ClickType == ClickType.Left)
{
}
}
Edit:
Also remember that you can subscribe multiple events to the same handler if you want to handle more than one click type:
eventAggregator.GetEvent<ClickEvents.SingleLeft>.Subscribe(HandlerMethod);
eventAggregator.GetEvent<ClickEvents.SingleRight>.Subscribe(HandlerMethod);
(this would work in the rare situation that the subscriber didn't care which mouse button was clicked)
I think you missed one possibility. You see, you don't have to create a new class for each notification. Instead, you are free to reuse classes but carry some additional state of arbitrary complexity inside.
public class MouseClickNotification {
public bool IsDoubleClick;
public MouseButton ClickedButton;
// any additional stuff
This way it is you who precisely define the granularity of your notification model.

Categories