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.)
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.
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.
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 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
I have run into a bit of a design issue with my code.
I have a object that creates a child object (the child could then create another child, etc), and both objects subscribe to the same event.
But, I only want the most child object to receive the event.
Overview of what my project is:
I am creating a IVR system. When a user calls into the system, the user will have X menu choices. Based on what the user chooses they will have a sub menu of choices, and so on and so on. I am using State Machines for this. Every State Machine needs to "listen" for when the user presses a number on their phone. But only the current State Machine needs to process the entered number. Each State Machine can create a new State Machine to represent the sub menu.
Here is some sample code:
Base class:
public delegate void DoSomething(object sender, EventArgs data);
public class Base
{
public event DoSomething myEvent;
private IObject foo;
public Base ()
{
foo = new myObjectA(this);
}
public void SomeAction()
{
((myObjectA)foo).CreateChild();
}
public void EventFired()
{
if (myEvent != null)
{
myEvent(this, new EventArgs());
}
}
}
ObjectA:
class myObjectA : IObject
{
private Base theCallingObject;
private IObject child;
public myObjectA (Base _base)
{
theCallingObject = _base;
theCallingObject.myEvent += new DoSomething(theCallingObject_myEvent);
}
public void CreateChild()
{
child = new myObjectB(theCallingObject);
}
void theCallingObject_myEvent(object sender, EventArgs data)
{
// Handle event
MessageBox.Show("myObjectA");
}
}
ObjectB:
class myObjectB : IObject
{
private Base theCallingObject;
public myObjectB (Base _base)
{
theCallingObject = _base;
theCallingObject.myEvent += new DoSomething(theCallingObject_myEvent);
}
void theCallingObject_myEvent(object sender, EventArgs data)
{
// Handle event
MessageBox.Show("myObjectB");
}
}
Now when I do this:
Base blah = new Base();
blah.SomeAction();
blah.EventFired();
I get message boxes for both A and B.
I need to implement Base so that only myObjectB gets the event.
I will have hundreds of myObject's so I need a implementation at the Base level and NOT the myObject level. Plus, handling it at the myObject level would still require the event to be fired causing performance issues if there are hundreds of objects.
One solution I have considered is when myObjectA creates the child, unsubscribe from the event, then resubscribe when we get back to the myObjectA level. However I feel something better could be done.
Anyone have any ideas?
Edit: Using payo's input I have come up with this:
public delegate void DoSomething(object sender, EventArgs data);
public class Base
{
private IObject foo;
private List<DoSomething> _myEventStorage;
public event DoSomething myEvent
{
add
{
_myEventStorage.Insert(0, value);
}
remove
{
_myEventStorage.Remove(value);
}
}
public Base ()
{
_myEventStorage = new List<DoSomething>();
foo = new myObjectA(this);
}
public void SomeAction()
{
((myObjectA)foo).CreateChild();
}
public void EventFired()
{
_myEventStorage[0].Invoke(this, new EventArgs());
}
}
you would need to explicitly implement myEvent (add/remove) handlers and track the "farthest" independently of the registered observers. then you can send the notification to that single instance.
For events, each subscriber is queued up (put at end of list), a FIFO model. You want the most-child object to 'own' the event, not just subscribe and be part of some abstract list of other unknown objects.
I would provide a new model that represents what you are trying to do. This might be what Jason recommended: (he posted his answer as I was typing this out)
public class Base
{
private DoSomething _myEventStorage;
public event DoSomething myEvent
{
add
{
_myEventStorage = value;
}
remove
{
_myEventStorage -= value;
}
}
...
public void EventFired()
{
if (_myEventStorage != null)
{
_myEventStorage(this, new ChainEventArgs());
}
}
}
This calls last ONLY. Another option (to add to this custom add/remove) would be to provide a derived EventArgs:
public class ChainEventArgs : EventArgs
{
public bool Handled { get; set; }
}
public delegate void DoSomething(object sender, ChainEventArgs data);
...
public event DoSomething myEvent
{
add
{
var temp = _myEventStorage;
_myEventStorage = null;
_myEventStorage += value;
_myEventStorage += temp; // now all are called, but FILO
}
remove
{
_myEventStorage -= value;
}
}
At this point, you can either check Handled on each IObject
void theCallingObject_myEvent(object sender, ChainEventArgs data)
{
if (data.Handled)
return;
if (I_want_to_block_parents)
data.Handled = true;
// else leave it false
}
Or, add some complexity to your Base class and stop calling up the chain (let's the children have no need to check Handled). I'll show the solution with a List<> of delegates, but some MulticaseDelegate casts and calls could do the same. I just feel the List<> code might be more readable/maintainable.
public class Base
{
private List<DoSomething> _myEventStorage;
public event DoSomething myEvent
{
add
{
_myEventStorage.Insert(0, value);
}
remove
{
_myEventStorage.Remove(value);
}
}
...
public void EventFired()
{
var args = new ChainEventArgs();
foreach (var handler in _myEventStorage)
{
handler(this, args);
if (args.Handled)
break;
}
}
}