Add event to another event? c# - c#

class a
{
public event Action foo;
var zzz = new b();
foo += zzz.bar;
}
class b
{
public Action bar;
}
The above (pseudo) code works and compiles fine.
However, if i change bar to public event Action bar I cant then add it to foo.
Basically I would like to add one event to another. Im aware this could sound abit ridiculous.

IIRC you can't invoke events from another class directly.
class A {
public A() {
b = new B(this);
}
private B b;
public event Action Foo;
}
class B {
public B(A a) {
a.Foo += InvokeBar;
}
public event Action Bar;
private void InvokeBar() {
if (Bar != null)
Bar();
}
}

What do you want to achieve is something like this (I guess):
foo event is triggered:
call all foo subscribed event handlers plus all bar subscribed event handlers.
bar is triggered:
call all bar subscribed event handlers plus all foo subscribed event handlers.
class a
{
public event Action foo;
b zzz = new b();
public a()
{
// this allow you to achieve point (1)
foo += zzz.FireBarEvent;
// this allow you to achieve point (2)
zzz.bar += OnBar;
}
void OnBar()
{
FireFooEvent();
}
void FireFooEvent()
{
if(foo != null)
foo();
}
}
class b
{
public event Action bar;
public void FireBarEvent()
{
if(bar != null)
bar();
}
}
CAVEAT:
this code (if (1) and (2) options are both enabled) cause an infinite numbers of calls i.e.:
foo --> bar --> foo --> bar ...
that has to be managed properly.

If bar is a public event, then you use a lambda to invoke the bar event:
foo += () => zzz.bar();
This is not the exact syntax, researching...
This is not possible, because you cannot call the bar event from outside the class it is defined in.
You should use a solution like this;
class b {
public Action bar;
public void InvokeBar() {
if (bar != null) bar();
}
}
Then you can use InvokeBar as a target for your event.

Related

How to write a custom event handler adder method in C#

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;
}
}
}

C# Subscribing an Event

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.

Why can't we use assignment operator when adding Events dynamically?

I was trying to add dynamic events, but when i use assignment operator only it does not work, but if i use with += operator, it works, could you please help me understand this functionality.
The event you attach a handler to is, in fact, a collection of event handlers. The += for the handler is a semantical equivalent of the Add method of the list. The opposite of adding is removing, represented by the -= operator. You can read more about it in this article: http://msdn.microsoft.com/en-GB/library/ms366768.aspx
In case when the property is defined not as event but as Action<T>, the property is a container of one function reference. In this case the = should be used as the property is not a collection.
Example:
using System;
public class Program
{
public static void Main()
{
var my = new MyClass();
my.MyAction = msg => Console.WriteLine(msg);
my.MyAction("asdf");
my.MyEvent += (s, e) => Console.WriteLine("Event");
my.InvokeEvent();
}
public class MyClass {
public Action<string> MyAction { get; set; }
public event EventHandler MyEvent;
public void InvokeEvent() {
// the MyEvent can be called only within the MyClass
MyEvent(this, null);
}
}
}

How to make only farthest child receive shared event?

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;
}
}
}

How virtual events work in C#?

Below is the program I used for the test.
It prints (as expected):
Raise A
Event from A
Raise B
Event from B
Now, if we change first two lines of the Main to be:
A a = new B();
B b = new B();
the Program will print:
Raise A
Raise B
Event from B
which is also expected, as overriding event hides the private backing field in the base class and therefore events fired by the base class are not visible to clients of the derived class.
Now I am changing the same lines to:
B b = new B();
A a = b;
and the program starts printing:
Raise A
Raise B
Event from A
Event from B
What's going on?
class A
{
public virtual event EventHandler VirtualEvent;
public void RaiseA()
{
Console.WriteLine("Raise A");
if (VirtualEvent != null)
{
VirtualEvent(this, EventArgs.Empty);
}
}
}
class B : A
{
public override event EventHandler VirtualEvent;
public void RaiseB()
{
Console.WriteLine("Raise B");
if (VirtualEvent != null)
{
VirtualEvent(this, EventArgs.Empty);
}
}
}
class Program
{
static void Main(string[] args)
{
A a = new A();
B b = new B();
a.VirtualEvent += (s, e) => Console.WriteLine("Event from A");
b.VirtualEvent += (s, e) => Console.WriteLine("Event from B");
a.RaiseA();
b.RaiseB();
}
}
We have a single instance (of B) which has the following fields:
A.VirtualEvent: null
B.VirtualEvent: Two event handlers
The call to a.RaiseA() just prints "Raise A" - but nothing more, because the private field in A is null.
The call to b.RaiseB() prints the remaining three lines, because the event has been subscribed to twice (once to print "Event from A" and once to print "Event from B").
Does that help?
EDIT: To make it clearer - think of the virtual event as a pair of virtual methods. It's very much like this:
public class A
{
private EventHandler handlerA;
public virtual void AddEventHandler(EventHandler handler)
{
handlerA += handler;
}
public virtual void RemoveEventHandler(EventHandler handler)
{
handlerA -= handler;
}
// RaiseA stuff
}
public class B : A
{
private EventHandler handlerB;
public override void AddEventHandler(EventHandler handler)
{
handlerB += handler;
}
public override void RemoveEventHandler(EventHandler handler)
{
handlerB -= handler;
}
// RaiseB stuff
}
Now is it clearer? It's not quite like that because as far as I'm aware you can't override just "part" of an event (i.e. one of the methods) but it gives the right general impression.
You hooked up two event handlers to the same event. Since A and B are pointing to the same object, when you call b.RaiseB() both event handlers get fired. So first you're calling RaiseA which is a basecalss method. That prints Raise A. It then doesn't actually fire off the event because it's null. Then, you're raising B but TWO handlers are hooked up to it, therefore it first prints Raise B, and when the event fires, both handlers get called.
Try making your RaiseA function protected + virtual.
A rule of thumb: If derived class overrides event accessors, it must also override the function that invokes the event.

Categories