Not very familiar with declaring and using events and received error,
Event must be of delegate type
Basically want to pass IMyInterface as a dependency to another class where that class can subscribe to receive MyClassEvent events and the event data is MyClass.
public interface IMyInterface
{
event MyClass MyClassEvent;
}
public class Implementation: IMyInterface
{
event MyClass MyClassEvent;
public void OnSomethingHappened
{
MyClassEvent?.Invoke(); // pass MyClass to subscribers
}
}
public class AnotherClass(IMyInterface ...)
{
OnMyClassEvent(MyClass args)
{
// do something
}
}
You need to declare the event correctly and define the event args:
public class MyClassEventArgs : EventArgs { }
public interface IMyInterface
{
event EventHandler<MyClassEventArgs> MyClassEvent;
}
public class Implementation : IMyInterface
{
public event EventHandler<MyClassEventArgs> MyClassEvent;
public void OnSomethingHappened()
{
MyClassEvent?.Invoke(this, new MyClassEventArgs());
}
}
And to subscribe to it:
var implementation = new Implementation();
implementation.MyClassEvent += MyClassEvent;
private void MyClassEvent(object sender, MyClassEventArgs e) { ... }
Related
I have a class library that has a number of classes.
Any of these classes should be able to send a message (string) to the client at any point of time . I want to have a Generic Event that can be raised from a number of classes. I don't want a separate event for each class.
Something like this:
public class GenericEvent
{
// Here I have an event.
}
public class LibClass1
{
//Raise event here.
}
public class LibClass2
{
//Raise event here
}
public class Client
{
//Subscribe to the event here
}
Is this the right approach? If yes, how can it be achieved? The examples I looked up all have a separate event for each class.
It depends on what this event is and use cases, but one of the options is to use inheritance:
public class GenericEvent
{
// Here I have an event.
protected void RaiseEvent();
}
public class LibClass1 : GenericEvent
{
public voidDoSomethingAndRaiseEvent()
{
// ...
RaiseEvent();
}
}
This is how INotifiPropertyChanged is usually implemented.
If inheritance is impossible and you're using aggregation, LibClass1 and LibClass2 should act as some facade/decorator for GenericEvent: they must have their own event, which re-directs calls to GenericEvent's event and method(-s) to raise it:
public class GenericEvent
{
public event EventHandler SomeEvent;
// ...
}
public class LibClass1
{
private readonly GenericEvent _ge;
// ...
public event EventHandler SomeEvent
{
add { _ge.SomeEvent += value; }
remove { _ge.SomeEvent -= value; }
}
public void DoSomethingAndRaiseEvent()
{
// ...
SomeEvent?.Invoke(this, EventArgs.Emtpy);
}
}
public class MyEventArgs : EventArgs
{
// class members
}
public abstract class Lib
{
public event EventHandler ShapeChanged;
public virtual void OnShapeChanged(MyEventArgs e)
{
if (ShapeChanged != null)
{
ShapeChanged(this, e);
}
}
}
public class LibClass1 : Lib
{
//Raise event here.
}
public class LibClass2 : Lib
{
//Raise event here
}
static void Main(string[] args)
{
LibClass1 lib1 = new LibClass1();
LibClass2 lib2 = new LibClass2();
lib1.ShapeChanged += Lib1_ShapeChanged;
lib2.ShapeChanged += Lib1_ShapeChanged;
lib1.OnShapeChanged(new MyEventArgs());
}
Here full example create an abstract class in which you have the event.
I would work with inheritance. For example:
public class ParentClass : Form
{
public ParentClass() {
this.FormClosed += sendString;
}
private void sendString(object sender, FormClosedEventArgs e)
{
throw new NotImplementedException();
}
}
public class GenericEvent : ParentClass { }
public class LibClass1 : ParentClass { }
public class LibClass2 : ParentClass { }
public class Client : ParentClass { }
Now all of you Clases have the event of the ParentClass.
I have another approach.
Derive all of your classes from one single base class. (of course any library do that, .net or MFC or Qt or java framework).
you have a single event "event 1" in base class. In that event1 handler, raise "event 2".
Subscribe all your child classes to the "event2" of parent class and handle your business in respective child classes.
Suppose I have the following Interface:
interface IBook
{
event EventHandler<EventArgs> PageChanged;
}
which I could implement without difficulty for this class:
class Novel : IBook
{
public event EventHandler<EventArgs> PageChanged;
protected void OnPageChanged()
{
EventHandler<EventArgs> pageChanged = PageChanged;
if (pageChanged != null) pageChanged(this, EventArgs.Empty);
}
}
however, if I now have an object called Encyclopedia defined as:
class Encyclopedia : IBook
{
public class EncyclopediaEventArgs : EventArgs
{
public int Volume
{
get { return volume; }
}
private int volume;
public EncyclopediaEventArgs(int volume)
{
this.volume = volume;
}
}
public event EventHandler<EncyclopediaEventArgs> PageChanged;
protected void OnPageChanged(int volume)
{
EventHandler<EncyclopediaEventArgs> pageChanged = PageChanged;
if (pageChanged != null) pageChanged(this, new EncyclopediaEventArgs(volume));
}
}
which has all the workings of a Book, but with the added event argument field of Volume. When I compile, I get an error (as surmised I would):
error CS0738: 'Encyclopedia' does not implement interface member 'IBook.PageChanged'. 'Encyclopedia.PageChanged' cannot implement 'IBook.PageChanged' because it does not have the matching return type of 'System.EventHandler'
It states that it cannot implement IBook.PageChanged because System.EventHandler<System.EventArgs> is not the return type, even though EncyclopediaEventArgs derives from System.EventArgs.
My question, therefore, is, would it be possible to derive such a class as Encyclopedia which adds the additional Volume field to its event arguments?
(Any discussion is very much welcome as to why this is or is not a poor design/architecture decision!)
It seems fairly straight forward to do this:
interface IBook<T> where T : EventArgs
{
event EventHandler<T> PageChanged;
}
class Novel : IBook<EventArgs> { ... }
class Encyclopedia : IBook<Encyclopedia.EncyclopediaEventArgs> { ... }
If you still need a plain IBook then you would do this:
interface IBook { }
interface IBook<T> : IBook where T : EventArgs
{
event EventHandler<T> PageChanged;
}
It depends a bit on how you are going to use IBook. You could create a generic parameter for the EventArgs like so:
public interface IBook<TEventArgs> where TEventArgs : EventArgs
{
event EventHandler<TEventArgs> PageChanged;
}
public class Novel : IBook<EventArgs>
{
event EventHandler<EventArgs> PageChanged;
}
public class Encyclopedia : IBook<EncyclopediaEventArgs>
{
event EventHandler<EncyclopediaEventArgs> PageChanged;
}
But then you can't use IBook without the generic type if you need PageChanged for other purposes.
Another way is to just keep the event EventHandler<EventArgs> PageChanged; have the Encyclopedia implementation pass a EncyclopediaEventArgs and just cast in the event handler.
class Encyclopedia : IBook
{
public class EncyclopediaEventArgs : EventArgs
{
}
public event EventHandler<EventArgs> PageChanged;
protected void OnPageChanged(int volume)
{
EventHandler<EventArgs> pageChanged = PageChanged;
if (pageChanged != null) pageChanged(this, new EncyclopediaEventArgs(...));
}
}
public class BookReader
{
public void OnPageChanged(object sender, EventArgs e)
{
if (sender is Encyclopedia && e is EncyclopediaEventArgs)
{
EncyclopediaEventArgs ee = (EncyclopediaEventArgs)e;
}
else
{
}
}
}
I have defined a Foo class and used this in Bar class, with a event handler:
public class Bar
{
public Bar()
{
Foo foo = new Foo();
foo.my_custom_event += my_event_handler;
}
public void my_event_handler()
{
// do work here
}
}
and this works perfectly. But I need to define a method in Foo class that will be fired when I add an event handler to my_custom_event, like:
public class Foo
{
...
public/private void my_event_handler_adder(target_function)
{
functions_that_are_fired_on_my_custom_event.Append(target_function);
}
}
Is there any way to define such an adder method?
class Foo
{
private EventHandler explicitEvent;
public event EventHandler ExplicitEvent
{
add
{
explicitEvent += value;
FireNeededMethodHere();
}
remove
{
explicitEvent -= value;
}
}
}
My interface has an event that don't has an arguments
public interface IMyInterface
{
event EventHandler OnSomethingHappened;
}
Here is how I am implementing it.
public class MyBaseClass : IMyInterface
{
private event EventHandler onSomethingHappened;
public event EventHandler OnSomethingHappened
{
add
{
onSomethingHappened-= value;
onSomethingHappened+= value;
}
remove
{
onSomethingHappened-= value;
}
}
}
But somehwere else when I try to use it as follows
if ( MyBaseClassInstance.OnSomethingHappened != null )
MyBaseClassInstance.OnSomethingHappened();
I get following compilation error
The event 'ConsoleApplication1.IMyInterface.OnSomethingHappened' can
only appear on the left hand side of += or -=
What am I doing wrong?
This is how your code might look:
public interface IMyInterface
{
event EventHandler OnSomethingHappened;
}
//implement the interface
public class MyBaseClass : IMyInterface
{
public event EventHandler OnSomethingHappened;
public void DoSomeLogicWhichRaisesTheEvent()
{
if (OnSomethingHappened != null)
{
MyBaseClass sender = this;
var eventArgs = new EventArgs();
//let all subscibers to event know that the event happened
OnSomethingHappened(sender, eventArgs);
}
}
}
public class ConsumerClass
{
private IMyInterface myBaseClassInstance;
public ConsumerClass()
{
myBaseClassInstance = new MyBaseClass();
//attach to the event
myBaseClassInstance.OnSomethingHappened += MyBaseClassInstance_OnSomethingHappened;
}
private void MyBaseClassInstance_OnSomethingHappened(object sender, EventArgs e)
{
//react to the raised event
throw new NotImplementedException();
}
}
As you can see you need to implement the IMyInterface interface, and when MyBaseClass needs to raise the event you call OnSomethingHappened(sender, eventArgs);
ConsumerClass is where you need to consume, or to do something, as a reaction to the raised event.
You may consider to rename MyBaseClass to some other name, without 'Base' in it, because it is not an abstract class.
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.)