I used to utilize the following:
public event EventHandler OnComplete = delegate { };
I'm not sure, how this is called, is this an "event default initializer"??
But the problem appeared to be when I derived from EventArgs, created my own EventHandler and decided to use the same approach. Please, see:
public class MyEventArgs : EventArgs
{
int result;
public int Result
{
get
{
if (exceptionObject == null)
return result;
else
throw new InvalidOperationException();
}
internal set { result = value; }
}
Exception exceptionObject;
public Exception ExceptionObject
{
get { return exceptionObject; }
internal set { exceptionObject = value; }
}
}
public delegate EventHandler MyEventHandler(object sender, MyEventArgs e);
public class MyOperation
{
public event MyEventHandler OnOperationComplete = delegate { };
}
So, the line
public event MyEventHandler OnOperationComplete = delegate { };
causes the problem.
How can I make the proper default initialization for "my" events?
public event MyEventHandler OnOperationComplete = (sender, args) => { return null; };
I also think you meant to say:
public delegate void MyEventHandler(object sender, MyEventArgs e);
not
public delegate EventHandler MyEventHandler(object sender, MyEventArgs e);
public event Action OnDied = delegate { };
The easiest method
Related
I have this code :
public void SomeMethod()
{
MyClass clss = new MyClass(); //note: MyClass implements INotifyPropertyChanged
clss.DoSomething();
clss.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(MyEventHandler);
}
static void MyEventHandler(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
Debug.WriteLine("some property on MyClass has changed!");
}
This is working ok and when the property in SomeClass changes, MyEventHandler() is run.
But now I need to pass aditional data from SomeMethod() to MyEventHandler() , how can I do this?
* UPDATE *
ok I guess I should have explained better the whole problem: the method DoSomething() in MyClass makes a call to an external web service, passing it a callback so when the web service finish its work, it will call the callback, passing it a value with the result of the operation. Inside that callback, I am changing a property of the class to assign it the value received from the web service, thus triggering the propertyChanged event.
Then in the caller class, I subscribe to that event so I can do some things when it happens.
The final objective is, after calling DoSomething(), be able to wait until the web service has finished its job and returned a result, so I can then save some things in the database etc. and only then, return from SomeMethod()...
so this is MyClass, simplified:
public class MyClass : INotifyPropertyChanged
{
private long _wsReturnValue;
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
public long wsReturnValue
{
get { return _wsReturnValue; }
set {
_wsReturnValue = value;
OnPropertyChanged("wsReturnValue");
}
}
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new System.ComponentModel.PropertyChangedEventArgs(name));
}
public void DoSomething(object entity)
{
//here I just call external web service and returns, the webservice will call TheCallback() when finished
}
public void TheCallback(CommunicationEventArgs e)
{
this.wsReturnValue = e.res;
}
}
And this is the class that uses MyClass:
class MainClass
{
public void SomeMethod(object someObject)
{
MyClass clss = new MyClass(); //note: MyClass implements INotifyPropertyChanged
clss.DoSomething(someObject); //someObject contains data that I want to use later in the event handler
clss.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(MyEventHandler);
}
private static void MyEventHandler(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
//here I need to use the object someObject...
}
}
Not sure if this is even close to what you mean, but here you go;
class EventClass
{
public void SomeMethod()
{
MyClass clss = new MyClass(); //note: MyClass implements INotifyPropertyChanged
clss.DoSomething(new object());
clss.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(MyEventHandler);
}
private static void MyEventHandler(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
var customeEventArgs = (CustomEventArgs) e;
Debug.WriteLine("some property on MyClass has changed! Extra Data : {0}", customeEventArgs.ExtraData);
}
}
Implemented some more shell code to illustrate
internal class MyClass
{
public void DoSomething(object data)
{
var e = new CustomEventArgs("Property")
{
ExtraData = data
};
PropertyChanged?.Invoke(this, e);
}
public event PropertyChangedEventHandler PropertyChanged;
}
internal class CustomEventArgs : PropertyChangedEventArgs
{
public CustomEventArgs(string propertyName) : base(propertyName)
{
}
public object ExtraData { get; set; }
}
Any help? :)
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.
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()
I have an adapter pattern on a generic class that essentially adapts between types:
class A<T> { event EventHandler e; }
class Aadapter<T1, T2> : A<T1> { A<T2> a; Aadapter(A<T2> _a) { a = _a; } }
The problem is that A contains an event. I effectively want all event handlers assigned to Adapter to fall through to a.
It would be awesome if I could assign the a's event handler to adapter's event handler but this is impossible?
The idea here is that A is almost really just A but we need a way to adapt the them. Because of the way event's work I can't how to efficiently do it except manually add two event handlers and when they are called they "relay" the to the other event. This isn't pretty though and it would seem much nicer if I could have something like
class A<T> { event EventHandler e; }
class Aadapter<T1, T2> : A<T1> { event *e; A<T2> a; Aadapter(A<T2> _a) { a = _a; e = a.e; } }
in a sense we have a pointer to the event that we can assign a2's event to.
I doubt there is any simple way but maybe someone has some idea to make it work.
(BTW, I realize this is possible with virtual events but I'd like to avoid this if at all possible)
I think that this is what you are after:
class A<T>
{
public virtual event EventHandler e;
}
class Aadapter<T1, T2> : A<T1>
{
A<T2> a;
Aadapter(A<T2> _a) { a = _a; }
public override event EventHandler e
{
add { a.e += value; }
remove { a.e -= value; }
}
}
Or chain it
class A<T>
{
public event EventHandler e;
protected void ChainEvent(object sender, EventArgs eventArgs)
{
e(sender, eventArgs);
}
}
class Aadapter<T1, T2> : A<T1>
{
A<T2> a;
Aadapter(A<T2> _a)
{
a = _a;
a.e += ChainEvent;
}
}
Why is subscribing and forwarding events not pretty? I find it elegant.
Doing this is consistent with the way the rest of the adapter is implemented.
Even if you could use a pointer, it would be inconsistent because you wouldn't want to do that in every case.
For example, if you're adapting a class that implements INotifyPropertyChanged to an interface that does not, but exposes a couple of properties, such as "TitleChanged" and "MaxLengthChanged," you wouldn't then use a pointer. Your adapter would expose those two events, and consumers would subscribe. Your adapter would subscribe to the PropertyChanged event, and raise "TitleChanged" only when it gets notified that "Title" was modified, and "MaxLengthChanged" only when it gets notified that "MaxLength" was modified. All other notifications would be ignored.
I favour this approach as I find it straightforward, consistent and true to the pattern.
Example showing the "standard" methods to solve the problem. The first uses virtual events/methods while the second does a "doubled ended" forwarding scheme. Both have their pro's and cons but would be nice if there was an easier method that didn't grow with the number of events. What we would like to do is sort of combine the two events into one directly instead of indirectly which is what all this code does. (pointers would be such a method if they were possible in C#)
//#define __virtual
#define __direct
using System;
using System.Collections.Generic;
using System.Text;
namespace VirtualEvents
{
#if __virtual
#region
public class A<T>
{
public virtual event EventHandler e;
public virtual void Fire() { e(this, null); }
}
public class Aadapter<T1, T2> : A<T1>
{
A<T2> a;
public override event EventHandler e
{
add { a.e += new EventHandler(value); }
remove { a.e -= new EventHandler(value); }
}
public override void Fire()
{
a.Fire();
}
public Aadapter(A<T2> _a)
{
a = _a;
}
}
#endregion
#elif __direct
#region
public delegate EventHandler EventHandlerPtr();
public class eventPtr
{
public EventHandler _event;
}
public class A<T>
{
//internal EventHandler _event;
public eventPtr _event = new eventPtr();
public event EventHandler e
{
add { _event._event += value; }
remove { _event._event -= value; }
}
public void Fire() { _event._event(this, null); }
}
public class Aadapter<T1, T2> : A<T1>
{
A<T2> a;
public Aadapter(A<T2> _a)
{
a = _a;
this._event = a._event;
}
}
#endregion
#else
#region
public class A<T>
{
public event EventHandler e;
public void Fire() { e(this, null); }
}
public class Aadapter<T1, T2> : A<T1>
{
A<T2> a;
public Aadapter(A<T2> _a)
{
a = _a;
a.e += new EventHandler(a_e);
e += new EventHandler(Aadapter_e);
}
void Aadapter_e(object sender, EventArgs e)
{
a.e -= new EventHandler(a_e);
a.Fire();
a.e += new EventHandler(a_e);
}
void a_e(object sender, EventArgs e)
{
this.e -= new EventHandler(Aadapter_e);
Fire();
this.e += new EventHandler(Aadapter_e);
}
}
#endregion
#endif
class Program
{
static void Main(string[] args)
{
var a = new A<double>();
var q = new Aadapter<int, double>(a);
a.e += new EventHandler(a_e);
q.e += new EventHandler(q_e);
a.Fire();
q.Fire();
((A<int>)q).Fire();
Console.ReadKey();
}
static void a_e(object sender, EventArgs e)
{
Console.WriteLine("From a");
}
static void q_e(object sender, EventArgs e)
{
Console.WriteLine("From q");
}
}
}
(edit: the code now includes a new method which wraps the event in a class which now allows events to be assigned easily and effectively represents the "the pointer" case. Hopefully someone can improve upon these even more.)
I'm writing a class library for a Web API.
I have a base class and an interface with 30 blocks like this:
interface ISomethingApi {
void AuthenticateAsync(string username, string password);
event AsyncResponseHandler AuthenticateEnded;
void GetMemberAsync(string username);
event AsyncResponseHandler<Member> GetMemberEnded;
// more...
}
The base class called BaseHttpClient contains the implementation and all methods are empty and virtual.
class BaseHttpClient : ISomethingApi {
public virtual void GetMemberAsync(string username) {
throw new NotImplementedException();
}
public event AsyncResponseHandler<Member> GetMemberEnded;
// more...
}
Because the API is pretty non-standard, I am inheriting the base class with a XmlClient class. This class overrides virtual methods and do the job.
class XmlClient : BaseHttpClient {
public override void GetMemberAsync(string username) {
Member member;
// process here
// raising the event
GetMemberEnded(this, new AsyncResponseArgs<Member>(member));
// error: LogoffEnded can only appear on the left hand side of += or -=
}
}
The problem is I can't raise the events:
The event 'BaseHttpClient.LogoffEnded' can only appear on the left hand side of += or -=
A basic solution is to create methods in the base class like
protected void RaiseLogoffEnded(AsyncResponseArgs args) {
if (LogoffEnded != null) {
LogoffEnded(this, args);
}
}
But there are too many methods to create. I'd like to do something like:
public override void GetMemberAsync(string username) {
Member member;
// work done here
RaiseEvent(x => x.GetMemberEnded, new AsyncResponseArgs<Member>(member));
}
I suppose this is about reflection and expressions.
Is it a right way to do? (performace)
What documentation could I read to make this?
could you show me a valid code for this?
You could use a couple of static extension methods:
static class Extensions
{
public static void Raise(this EventHandler #event, object sender, EventArgs e)
{
if (#event != null)
#event(sender, e);
}
public static void Raise<T>(this EventHandler<T> #event, object sender, T e) where T : EventArgs
{
if (#event != null)
#event(sender, e);
}
}
Whereby you could do:
public class MyClass
{
public event EventHandler MyEvent;
public void DoSomething()
{
MyEvent.Raise(this, EventArgs.Empty);
}
}
While you can in fact use an expression, e.g.:
public void Raise<T>(Expression<Func<EventHandler<T>>> expr, T eventArgs)
where T : EventArgs
{
EventHandler<T> handler = expr.Compile().Invoke();
handler(this, eventArgs);
}
You probably want to do away with the redundant expression, and just use a Func<T> instead, as you are raising the event from the class directly. Through expressions, you would need to compile the expression, whereas Func<T> you don't:
public void Raise<T>(Func<EventHandler<T>> func, T eventArgs)
where T : EventArgs
{
EventHandler<T> handler = func();
handler(this, eventArgs);
}
You can make use of System.ComponentModel.EventHandlerList which will net you two advantages:
1) You will have your FireEvent mechanism.
2) The Events member doesn't use memory unless there are delegates subscribed. If you have a class with 30 events, you have 30 pointers in your class' footprint, whether or not there are any subscribers. EventHandlerList is a single object that contains any and all delegates subscribed. It's a very light-weight map (not a Dictionary). Notice that the event keys are static objects so as not to add to the class' footprint.
class AsyncResponseArgs : EventArgs
{
public Member Member { get; private set; }
public AsyncResponseArgs(Member m)
{
Member = m;
}
}
interface ISomethingApi
{
void AuthenticateAsync(string username, string password);
event EventHandler<AsyncResponseArgs> AuthenticateEnded;
void GetMemberAsync(string username);
event EventHandler<AsyncResponseArgs> GetMemberEnded;
}
class BaseHttpClient : ISomethingApi
{
private EventHandlerList Events = new EventHandlerList();
public virtual void AuthenticateAsync(string username, string password)
{
throw new NotImplementedException();
}
protected static object AuthenticateEndedEvent = new object();
public event EventHandler<AsyncResponseArgs> AuthenticateEnded
{
add { Events.AddHandler(AuthenticateEndedEvent, value); }
remove { Events.RemoveHandler(AuthenticateEndedEvent, value); }
}
public virtual void GetMemberAsync(string username)
{
throw new NotImplementedException();
}
protected static object GetMemberEndedEvent = new object();
public event EventHandler<AsyncResponseArgs> GetMemberEnded
{
add { Events.AddHandler(GetMemberEndedEvent, value); }
remove { Events.RemoveHandler(GetMemberEndedEvent, value); }
}
protected void FireEvent(object key, AsyncResponseArgs e)
{
EventHandler<AsyncResponseArgs> handler = (EventHandler<AsyncResponseArgs>)Events[key];
if (handler != null)
handler(this, e);
}
}
class XmlClient : BaseHttpClient
{
public override void GetMemberAsync(string username)
{
Member member;
// process here
FireEvent(GetMemberEndedEvent, new AsyncResponseArgs(member));
}
}
Added:
You can save yourself some typeing in BaseHttpClient by writing a code snippet.
You have to move your RaiseXXX methods to parent class, where you have your events defined. Make sure these methods are at least protected.
And don't forget to call your events via local variable to minimize error field.
var e = MyEvent;
if (e != null) e(this, EventArgs.Empty);
You could add a method to the base class that takes the event name as a String and raises the corresponding event via reflection like
public void Raise(String eventName, object source, EventArgs eventArgs)
{
var field = this.GetType().GetField(eventName, BindingFlags.Instance | BindingFlags.NonPublic);
if (field == null)
throw new ArgumentException("No such event: " + eventName);
var eventDelegate = (MulticastDelegate)field.GetValue(this);
if (eventDelegate != null)
foreach (var handler in eventDelegate.GetInvocationList())
handler.Method.Invoke(handler.Target, new object[] { source, eventArgs });
}
I don't know anything about performance, though.