Say I have a class just for specifying C# events and I pass this class around my application.
public class MyEvents
{
public event MyEventHandler OnBeforeSomeAction;
public event MyEventHandler OnSomeAction;
}
In order to invoke these events the invocation has to come from within the class itself. The easy way to let other classes trigger these events as MyEvents gets passed around the application would be to create public trigger functions.
public class MyEvents
{
public event MyEventHandler OnBeforeSomeAction;
public event MyEventHandler OnSomeAction;
public void TriggerOnBeforeSomeAction()
{
OnBeforeSomeAction();
}
public void TriggerOnSomeAction()
{
OnSomeAction();
}
}
However, if there are many events on this class then there would also have to be many trigger methods. Would there be a way to get the event using reflection and trigger it? Something like this:
public class MyEvents
{
public event MyEventHandler OnBeforeSomeAction;
public event MyEventHandler OnSomeAction;
public void TriggerEvent(string eventName)
{
var event = // some magic reflection.
event.Invoke();
}
}
Exactly what you want - taken from this fantastic page....
public void TriggerEvent(string handler, EventArgs e)
{
MulticastDelegate eventDelegate =
(MulticastDelegate)this.GetType().GetField(handler,
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.NonPublic).GetValue(this);
Delegate[] delegates = eventDelegate.GetInvocationList();
foreach (Delegate dlg in delegates)
{
dlg.Method.Invoke(dlg.Target, new object[] { this, e });
}
}
Related
I need to Raise an Event from another Class - i know that this is not possible - but I need a workaround for this.
For now Im doing the following
This is the class, which have to raise the event
internal class DataTransfer
{
public delegate void EventHandler(object sender, OnReaderCommonEventArgs e);
public event EventHandler _OnSerialNumber;
public event EventHandler _OnReaderType
Task DataHandler()
{
//Recieving-Data and Stuff
_OnSerialNumber(this, new OnReaderCommonEventArgs { SerialNumber = RFIDParser.ParseSerialNumber(data) });
_OnReaderType(this, new OnReaderCommonEventArgs { ReaderType = RFIDParser.ParseReaderType(data) });
}
}
And in the Main-Class, which will be used by the user. So the user can only subscribe to the event from this class-object:
public partial class PUR_100U
{
public delegate void EventHandler(object sender, OnReaderCommonEventArgs e);
public event EventHandler OnSerialNumber;
public event EventHandler OnReaderType;
public PUR_100U(int portnumber)
{
dataTransfer = new DataTransfer(portnumber, GetIdentifierList());
dataTransfer._OnSerialNumber += dataTransfer__OnSerialNumber;
dataTransfer._OnReaderType += dataTransfer__OnReaderType;
}
void dataTransfer__OnSerialNumber(object sender, OnReaderCommonEventArgs e)
{
if (OnSerialNumber != null) { OnSerialNumber(this, new OnReaderCommonEventArgs { SerialNumber = e.SerialNumber }); }
}
void dataTransfer__OnReaderType(object sender, OnReaderCommonEventArgs e)
{
if (OnReaderType != null) { OnReaderType(this, new OnReaderCommonEventArgs { ReaderType = e.ReaderType }); }
}
}
Example of user-usage:
rfid = new PUR_100U(20);
rfid.OnSerialNumber += rfid_OnSerialNumber;
rfid.OnReaderType += rfid_OnReaderType;
Is there a better way of doing this?
I need to Raise an Event from another Class - i know that this is not possible - but I need a workaround for this.
That is rather trivial:
class Foo
{
public event EventHandler Fooed; //note, name is not OnFoo
public void FireFooed() => Fooed?.Invoke(this, new EventArgs);
}
And now, fire the event at will:
var foo = new Foo();
foo.FireFooed();
The question is, why do you want to do this? It seems like a really bad idea. Fooed should fire only and only if the preconditions inside Foo for it to fire are met; if you need Fooed to fire, then make the preconditions happen!
Firing Fooed at will if the conditions aren't met will break all other listeners, don't do that.
What would be the equivalent C# code against following VB.Net code:
Public Event EndOfVideo()
Private Sub RaiseEndOfVideo()
RaiseEvent EndOfVideo()
End Sub
EDIT
Here is the equivalent C# code that telerik converter generated for me.
public event EndOfVideoEventHandler EndOfVideo;
public delegate void EndOfVideoEventHandler();
private void RaiseEndOfVideo()
{
if (EndOfVideo != null) {
EndOfVideo();
}
}
Calling RaiseEndOfVideo doesn't trigger/invoke EndOfVideo event, and Null Reference Exception is raised.
Consider you have class VideoPlayer which has event EndOfVideo and you want to raise this event and when someone calls method EndVideo on object of VideoPlayer.
Now, like any other member of a class event also initialized to null and gets the value when some handler is attached to it.
Attaching an handler to an event happens using += operator.
public class VideoPlayer
{
public event EndOfVideoEventHandler EndOfVideo;
// Following delegate indicates that the a method accepting no parameter
// and returning void can be attached as an handler to this event.
public delegate void EndOfVideoEventHandler();
public void EndVideo()
{
RaiseEndOfVideo();
}
private void RaiseEndOfVideo()
{
if (EndOfVideo != null)
{
// Following line of code executes the event handler which is
// attached to the event.
EndOfVideo();
}
}
}
public class WebPage
{
public void VideoStopped()
{
Console.WriteLine("Video Stopped");
}
}
Now in Main method of program.cs
static void Main(string[] args)
{
VideoPlayer player = new VideoPlayer();
WebPage page = new WebPage();
player.EndOfVideo += page.VideoStopped;
// Following method call on player object will call internally
// RaiseEndOfVideo which will Raise event and event will execute
// VideoStopped method of page object which is attached in previous line
// and display "Video Stopped" message in Console.
player.EndVideo();
Console.WriteLine("Completed!!! Press any key to exit");
Console.ReadKey();
}
I hope this would help you start understanding how events and delegates work in C#. For further reading you can go thru https://msdn.microsoft.com/en-us/library/edzehd2t(v=vs.110).aspx
This is the generally accepted way to write an event with no parameters:
public class Foo
{
public event EventHandler EndOfVideo;
protected virtual void OnEndOfVideo()
{
var handler = EndOfVideo;
if (handler != null)
handler(this, EventArgs.Empty);
}
}
Your code is what was needed in the old days: creating a delegate and yada yada.
To state the obvious, though, you need to subscribe to an event with something like:
public class Bar
{
public void DoAllTheThings()
{
var foo = new Foo();
foo.EndOfVideo += foo_EndOfVideo;
}
void foo_EndOfVideo(object sender, EventArgs e)
{
Console.WriteLine("EndOfVideo");
}
}
For the sake of completeness, the EventHandler delegate has a generic counterpart, EventHandler<T>, which you would use when you want an event that does have parameters, where T should be a class inheriting from System.EventArgs which holds the information you want your event to expose.
To do that, you will need to create a custom eventHandler to specify the method signatures of the handlers for your event
I have a class with an EventHandler for TimeChanged. A couple of instances of this class are created. In one of the instances of the class, the time can be changed. I would like all instances to react to the event of changed time.
Example:
public class MainClass
{
public MainClass()
{
}
public event EventHandler TimeChanged;
private virtual void OnTimeChanged()
{
EventHandler handler = TimeChanged;
if(handler != null)
{
handler(this, eventArgs.Empty);
}
}
}
public class AnotherClass
{
public AnotherClass()
{
MainClass _mainClass = new MainClass();
}
private void OnLoaded()
{
_mainClass.TimeChanged += HandleTimeChanged;
}
private void HandleTimeChanged
{
//Some stuff happens with new time, etc.
}
}
public class TimeClass
{
MainClass _class = new MainClass();
TimeSpan _timeValue;
private void ChangeTime()
{
// This is where the _timeValue is changed
// All instances of MainClass, subscribed to TimeChanged event to be notified with the new value selected.
}
}
So, basically when I change the time in TimeClass, which contains an instance of MainClass, I want to fire the TimeChanged event and all instances of MainClass (like in AnotherClass) should respond to the TimeChanged event to which they subscribed.
Hope this explains the situation. Any suggestions are welcome. Thanks.
I have the following code with 3 different classes. I am trying to
Subscribe event from class B to method (event handler) defined in
class ControlSystem. All compiles fine, it works no problem but the event handler method is never triggered... What am I doing wrong?
namespace EventTest
{
public class ControlSystem : CrestronControlSystem
{
A myObject = new A();
public ControlSystem(): base()
{
Thread.MaxNumberOfUserThreads = 100;
// Subscribe Event
myObject.mySubObject.BEvent += HandleBEvent;
// Throw Event
myObject.mySubObject.ThrowEvent();
}
public override void InitializeSystem()
{
}
public void HandleBEvent(object sender, EventArgs args)
{
Console.WriteLine("Something happend to {0}", sender);
}
}
public class A
{
public B mySubObject;
public A()
{
mySubObject = new B();
}
}
public class B
{
public EventHandler BEvent;
public B(){}
public void ThrowEvent()
{
EventHandler handler = BEvent;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
}
Real code links below (it works with Embeded system so you won't be able to compile it). Idea is to have button press to trigger an event which could
alarm other UIs that something happend to it.
http://ideone.com/NJz2Ek
Thanks
You are missing the event keyword.
public event EventHandler BEvent;
is what needs to be there.
I am working a problem which is about delegate and event. I am a newbid in this aspect. I don't know how to call the event.
Would some tell me?
Thanks in advance.
Here is simple example to call event....
// event_keyword.cs
using System;
public delegate void MyDelegate(); // delegate declaration
public interface I
{
event MyDelegate MyEvent;
void FireAway();
}
public class MyClass: I
{
public event MyDelegate MyEvent;
public void FireAway()
{
if (MyEvent != null)
MyEvent();
}
}
public class MainClass
{
static private void f()
{
Console.WriteLine("This is called when the event fires.");
}
static public void Main ()
{
I i = new MyClass();
i.MyEvent += new MyDelegate(f);
i.FireAway();
}
}
There is Link which may helpful.
The event can be invoked in the class in which it is declared. First you'll usually want to check if your event is null.
if (MyEvent != null) MyEvent(this, new EventArgs());
The arguments you pass to the event will depend on the declaration of the event. To give you a little more background, an event is just a compiler trick. When an event such as
public event ChangedEventHandler Changed;
is compiled it will look like
protected ChangedEventHandler _change;
public ChangedEventHandler Change
{
add { _change += value; }
remove { _change -= value; }
}
so anything inside where it is declared will use _change, while anything outside will use Change. In other words, inside where it is declared, it is just a delegate, and all the normal rules apply.
To resuse the event you just need to attach event with the you control for example .
buttonone.Click+= event1;
buttonTwo.Click+= event1;
Fore more details have look : C# Event Implementation Fundamentals, Best Practices and Conventions
Once you have defined the delegate, you need to define when to call the event. I mean you can call the event at assignment of any value to the specific variable.
here is the example of defining the delegate with the same variable class.
public class callbackdel : EventArgs
{
public readonly string resp = null;
public callbackdel(string s)
{
resp = s;
}
}
public delegate void WorkerEndHandler(object o, callbackdel e);
Now in the control you are using, you need to add this method.
public void OnWorkEnd(object o, callbackdel e)
{
WorkEnd(o, e);
}
after creating method and defining the delegate, you can fire the event from any of the delegate simply by calling the method.
OnWorkEnd((object)this, e);
When using an Event you first have to declare it:
// Create some custom arguments for the event
public class SampleEventArgs
{
public SampleEventArgs(string s)
{
Text = s;
}
public String Text {get; private set;}
}
// Define a class that uses the event
public class EventPublisher
{
// Declare the delegate
public delegate void SampleEventHandler(object sender, SampleEventArgs e);
// Declare the event.
public event SampleEventHandler SampleEvent;
// Wrap the event in a protected virtual method
// to enable derived classes to raise the event.
protected virtual void RaiseSampleEvent()
{
// Raise the event by using the () operator.
if (SampleEvent != null)
SampleEvent(this, new SampleEventArgs("Hello"));
}
}
You can then subscribe to the event:
EventPublisher publisher = new EventPublisher();
publisher.SampleEvent += new EventPublisher.SampleEventHandler(SampleEventHandler);
public void SampleEventHandler(object sender, SampleEventArgs args)
{
}
Your event handler will be called when EventPublisher executes RaiseSampleEvent()