Is there any way of being notified when something subscribes to an event in my class, or do I need to wrap subscription/unsubsription in methods eg:
public class MyClass : ISomeInterface
{
public event SomeEventHandler SomeEvent; //How do I know when something subscribes?
private void OnSomeEventSubscription(SomeEventHandler handler)
{
//do some work
}
private void OnSomeEventUnsubscription(SomeEventHandler handler)
{
//do some work
}
}
instead of
public class MyClass : ISomeInterface
{
private SomeEventHandler _someEvent;
public void SubscribeToSomeEvent(SomeEventHandler handler)
{
_someEvent += handler;
//do some work
}
public void UnsubscribeFromSomeEvent(SomeEventHandler handler)
{
_someEvent -= handler;
//do some work
}
}
The reason I ask is because the event is already exposed directly on a ISomeInterface but this particular implementation needs to know when stuff subscribes/unsubscribes.
You can write custom accessors for your event:
private SomeEventHandler _someEvent;
public event SomeEventHandler SomeEvent
{
add
{
_someEvent += value;
Console.WriteLine("Someone subscribed to SomeEvent");
}
remove
{
_someEvent -= value;
Console.WriteLine("Someone unsubscribed from SomeEvent");
}
}
Thomas has answered this already but thought I'd also add that you may need to lock any critical section in the add remove sections since event subscription is never thread safe, i.e. you have no idea who is going to connect to you or when. E.g.:
private readonly object _objectLock = new object();
private SomeEventHandler _someEvent;
public event SomeEventHandler SomeEvent
{
add
{
lock(_objectLock)
{
_someEvent += value;
// do critical processing here, e.g. increment count, etc could also use Interlocked class.
} // End if
} // End of class
remove
{
lock(_objectLock)
{
_someEvent -= value;
// do critical processing here, e.g. increment count, etc could also use Interlocked class.
} // End if
} // End if
} // End of event
Related
i have an event where i register event handlers.
event Action OnGameList;
then for example i reach some code like this:
backend.OnGameList += ProcessGameList;
backend.GetGameList(); //this will trigger the above event.
every time i reach this code, the handler is ADDED. that means the second time it will be called twice.
of course i could remove it in the function like this:
backend.OnGameList -= ProcessGameList;
but i have the feeling that there is a better solution for this kind of problem.
I think you should use some kind of backing field to track that you are already subscribed. I.e.
private bool _subscribed = false;
SubscribeToOnGameListEvent();
backend.GetGameList();
private void SubscribeToOnGameListEvent()
{
if (!_subscribed)
{
backend.OnGameList += ProcessGameList;
_subscribed = true;
}
}
You can check the presence of particular delegate in invocation list:
class Foo
{
private EventHandler bar;
public event EventHandler Bar
{
add
{
if (bar == null)
{
bar = value;
}
else
{
if (!bar.GetInvocationList().Contains(value))
{
bar += value;
}
}
}
remove
{
// ...
}
}
public void RaiseBar()
{
if (bar != null)
{
bar(this, EventArgs.Empty);
}
}
}
Is it possible to execute some code when someone subscribes to an event that i made in my class. a short explenation: i need to configure an external pc to send data to me when someone subscribes to this event, so when that data is received i can throw the event.
public class test
{
public event EventHandler myEvent;
private void Method1()
{
//this needs to be executed when someone subscribes to the event
}
private void Method2()
{
//this needs to be executed when someone unsubscribes to the event
}
}
You can create your add / remove methods
private EventHandler myEvent;
public event EventHandler MyEvent {
add {
myEvent += value;
if(myEvent != null) ExecuteCode();
}
remove {
myEvent -= value;
}
}
be careful if your function should be thread-safe, in which case you need a lock in order to ensure it to be synched.
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;
}
}
}
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 a plain normal class, e.g.:
public class ObjectA
{
public string val {get;set;}
...
}
in another class, it holds an instance of ObjectA, e.g.:
public class ObjectB
{
private ObjectA objectA;
....
}
the instance "objectA" will be frequently changed.
i mean in ObjectB, some of the method will new and new instance of Object A and assign to "objectA"
is there a way to implement a trigger, whenever instance objectA is change, will allow me to do something, e.g.:
objectA += OnChanged_ObjectA
protected void OnOnChanged_ObjectA()
{
// do something
}
You can create a change event on ObjectA that you will fire for any of the changes you wish to track. This will allow you to subscribe to this event on any other object, including ObjectB.
In Object1.cs:
// Delegate type for the event handler
public delegate void MyEventHandler();
// Declare the event.
public event MyEventHandler MyEvent;
// In the properties or any place you what to notify of change:
if (MyEvent != null)
MyEvent();
And in Object2.cs you can subscribe:
objectA.MyEvent += OnChanged_ObjectA
protected void OnOnChanged_ObjectA()
{
// Action changes
}
How about :
INotifyPropertyChanged Interface
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged.aspx
I had such problem recently, but unfortunately, I didn't find any another solution, but this:
public ObjectB
{
private ObjectA _objectA;
public ObjectA objectA
{
get
{
return _objectA;
}
set
{
if (value != _objectA)
{
_objectA = value;
RaiseObjectAChanged(/* sender, args */);
}
}
}
private RaiseObjectAChanged()
{
// raise event here
}
private OnObjectAChanged()
{
// event handler
}
}