What is the purpose of using myevent(this,EventArgs.Empty)? - c#

I am currently learning about delegates and events in csharp.I have the following set of codes:
using System;
using System.Collections.Generic;
using System.Text;
public delegate void mydel(object sender, EventArgs e);
class event1
{
public event mydel myevent;
public void onfive()
{
Console.WriteLine("I am onfive event");
Console.ReadKey();
if (myevent != null)
{
myevent(this,EventArgs.Empty);
}
}
}
public class test
{
public static void Main()
{
event1 e1 = new event1();
e1.myevent += new mydel(fun1);
Random ran = new Random();
for (int i = 0; i < 10; i++)
{
int rn = ran.Next(6);
Console.WriteLine(rn);
Console.ReadKey();
if (rn == 5)
{
e1.onfive();
}
}
}
public static void fun1(object sender, EventArgs e)
{
Console.WriteLine(" i am surplus function called due to use of '+=' ");
Console.ReadKey();
}
}
Whenever i put the following lines in comment the fun1() function is not called.Why it it so?
if (myevent != null)
{
myevent(this,EventArgs.Empty);
}
what is the purpose of these lines?

That bit of code is what raises the event. If the event is not raised then the event handler is not executed.
A delegate is an object that refers to a method and an event is sort of like a collection of delegates. If you don't add any handlers to an event then there is no collection, hence the check for null. If the event is not null then that means that handlers have been registered. The line inside the if statement raises the event, which means invoking each of the delegates in the collection. As each delegate is invoked, so the method it refers to is executed. The method that gets executed is your event handler.

EventArgs :
The EventArgs are arguments that the implementor of this event may find useful. With OnClick it contains nothing good, but in some events, like say in a GridView 'SelectedIndexChanged', it will contain the new index, or some other useful data.
EventArgs.Empty: Used to Pass the value to event handlers that are associated with events that do not have data.
Your event is of type mydel.
public mydel myevent; // declaring an event of type mydel with signature void mydel()
Hope this might give you some spark.

if (myevent != null) //Checks so you instantiated a event
{
myevent(this,EventArgs.Empty); // {this} will be equal to the sender in delegete myDel, {EventArgs.Empty} is since you are not passing any arguments to your delegate.
}

Related

How to represent any event and any function in C#?

I had the idea of developing a class to manage events unsubscriptions in a safe way so I don't have to manually write -= to each event subscription of this system when the time comes (in this system there are groups of events that are subscribed and unsubscribed together).
I thought of creating a class that manages a Dictionary where the key is an event (any possible event) and the value is a method (any possible method). This way I would have a method to subscribe a function to an event and it will do that alongside registering the pair in the Dictionary; and another method to unsubscribe all events added with this class (which would just iterate the dictionary and unsubscribe all events).
Thing is: I can't find how to have a common type of any event that I could use as generic argument to the dictonary's key and also I don't know how to represent any function in C# to set as the dictionary's value. In C/C++ I could just treat them both as void pointers as all I would need is the pointer of the function itself.
Is that even possible to do using C#? Are there existing better methods/strategies to accomplish that?
You will have to come up with a way of generating the key for the event, since you can't use a plain event as a dictionary key. One way to do that would be to concatenate the event's declaring class name with the name of the event.
Then you could use a dictionary using that as a key, with a List<Action> as the value. Here, the Action would be a delegate that you could call to unsubscribe.
You could wrap that dictionary in a class to provide Subscribe() and Unsubscribe() methods like so:
using System;
using System.Collections.Generic;
namespace ConsoleApp2
{
class Program
{
static void Main()
{
string eventKey = test.GetType().FullName + '.' + nameof(test.MyEvent);
subs.Subscribe(eventKey, () => test.MyEvent += handler, () => test.MyEvent -= handler);
subs.Subscribe(eventKey, () => test.MyEvent += handler, () => test.MyEvent -= handler);
test.RaiseEvent(); // Two handlers called.
subs.Unsubscribe(eventKey);
test.RaiseEvent(); // No handlers called (both were unsubscribed).
}
static void handler(object sender, EventArgs args)
{
Console.WriteLine("Handling event.");
}
static readonly Test test = new Test();
static readonly EventSubscriptions subs = new EventSubscriptions();
}
public class EventSubscriptions
{
public void Subscribe(string key, Action subscribe, Action unsubscribe)
{
subscriptions.TryGetValue(key, out var subs);
if (subs == null)
{
subs = new List<Action>();
subscriptions.Add(key, subs);
}
subscribe();
subs.Add(unsubscribe);
}
public void Unsubscribe(string key)
{
subscriptions.TryGetValue(key, out var subs);
if (subs != null)
{
foreach (var unsub in subs)
{
unsub();
}
subscriptions.Remove(key);
}
}
readonly Dictionary<string, List<Action>> subscriptions = new Dictionary<string, List<Action>>();
}
class Test
{
public event EventHandler<EventArgs> MyEvent;
public void RaiseEvent()
{
MyEvent?.Invoke(this, EventArgs.Empty);
}
}
}
Assuming all of your event handlers are of the void MyHandler(object sender, EventArgs e) variety, your dictionary would be Dictionary<string, Action<object,EventArgs>> (assuming you wanted the key to be string - anything else would work too)

Subscribing and unsubscribing from a method instead of a delegate?

I know there are times you need to keep track of a delegate so that it can be unsubscribed properly:
private EventHandler _handler;
public void Foo()
{
if (_handler != null)
{
Something.SomeEvent -= _handler; // Unsubscribe old event
}
_handler = delegate(object sender, EventArgs args) { };;
Something.SomeEvent += _handler;
}
But, is that still necessary if you use a method instead?
public void CustomMethod(object sender, EventArgs args) { ... }
public void Foo()
{
// Not sure how to unsubscribe only if it wasn't subscribed first?
if (some way to check)
{
Something.SomeEvent -= CustomMethod;
}
Something.SomeEvent += CustomMethod;
}
No, it's not necessary. If you are always subscribing/unsubscribing the same method (in the form of a delegate), then you don't need to track the actual delegate instance that was subscribed. The new delegate instances (implicitly created for you by the C# compiler in the += and -= operations) are correctly identified as identical, so that the -= operation removes the delegate that was added in the += operation.
In other words, equality for the Delegate class is not just "reference equality". Two completely different Delegate instances that have the same invocation list are considered equal.
If you wanna check if a specific method subscribed or not you can use GetInvocationList and then Linq:
var mInfo = typeof(SomeType).GetMethod("CustomMethod");
if(Something.SomeEvent.GetInvocationList().Any(x => x.Method == mInfo))
{
}

Raise event through a general method

I'm trying to create a reusable method for a more complicated event execution. I can't get it to compile or run with framework events that don't follow the EventHandler<Type> pattern. I would like to avoid reflection if possible as it will be a heavily used event.
I've created a test console app below which illustrates the problem:
using System;
using System.Collections.Specialized;
namespace CallEventsViaMethod
{
public class TestEventArgs : EventArgs { }
class Program
{
static void Main(string[] args)
{
MyProgram program = new MyProgram();
program.Go();
Console.ReadKey(false);
}
}
public class MyProgram
{
public event EventHandler<TestEventArgs> TestEvent;
public event NotifyCollectionChangedEventHandler CollectionChangedEvent;
public void Go()
{
TestEvent += new EventHandler<TestEventArgs>(MyProgram_TestEvent);
CollectionChangedEvent += new NotifyCollectionChangedEventHandler(MyProgram_CollectionChangedEvent);
// Want a reusable method I can use to conditionally execute any event
GeneralEventExecutor.Execute<TestEventArgs>(TestEvent, new Object(), new TestEventArgs());
GeneralEventExecutor.Execute<NotifyCollectionChangedEventArgs>(TestEvent, new Object(), new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
void MyProgram_TestEvent(object arg1, TestEventArgs arg2)
{
Console.WriteLine("Custom event ran");
}
void MyProgram_CollectionChangedEvent(object sender, NotifyCollectionChangedEventArgs e)
{
Console.WriteLine("NotifyCollectionChangedEventHandler event ran");
}
}
public static class GeneralEventExecutor
{
public static void Execute<T>(EventHandler<T> eventToRaise, object sender, T eventArgs) where T : EventArgs
{
if (eventToRaise == null)
return;
Delegate[] registeredEventHandlers = eventToRaise.GetInvocationList();
foreach (EventHandler<T> eventHandler in registeredEventHandlers)
{
object target = eventHandler.Target; // Need access to the Target property
// * Code deciding if should invoke the event handler *
eventHandler.Invoke(sender, eventArgs);
}
}
}
}
Error messages are:
error CS1502: The best overloaded method match for
'CallEventsViaMethod.GeneralEventExecutor.Execute(System.EventHandler,
object,
System.Collections.Specialized.NotifyCollectionChangedEventArgs)' has
some invalid arguments
error CS1503: Argument 1: cannot convert from
'System.EventHandler' to
'System.EventHandler'
I understand why I'm getting the error, but can't figure out a way round it.
Replace your your generic Execute<T> as below
public static void Execute<T>(Delegate eventToRaise, object sender, T eventArgs) where T:EventArgs
{
if (eventToRaise == null)
return;
Delegate[] registeredEventHandlers = eventToRaise.GetInvocationList();
foreach (Delegate eventHandler in registeredEventHandlers)
{
object target = eventHandler.Target; // Need access to the Target property for conditions
// * Code deciding if should invoke the event handler *
eventHandler.DynamicInvoke(sender, eventArgs);
}
}

One shot events using Lambda in C#

I find myself doing this sort of thing quite often:-
EventHandler eh = null; //can't assign lambda directly since it uses eh
eh = (s, args) =>
{
//small snippet of code here
((SomeType)s).SomeEvent -= eh;
}
variableOfSomeType.SomeEvent += eh;
Basically I only want to attach an event handler to listen for one shot from the event, I no longer want to stay attached after that. Quite often that "snippert of code" is just one line.
My mind is going a bit numb, I'm sure there must be something I can do so I don't need to repeat all this overhead. Bear in mind that EventHandler may well be EventHandler<T>.
Any ideas how I can tidy up the repeative part of the code and just leave the snippet in a Lambda?
You could attache a permanent event handler to the event. The event handler then invokes "one shot event handlers" that are added to an internal queue:
OneShotHandlerQueue<EventArgs> queue = new OneShotHandlerQueue<EventArgs>();
Test test = new Test();
// attach permanent event handler
test.Done += queue.Handle;
// add a "one shot" event handler
queue.Add((sender, e) => Console.WriteLine(e));
test.Start();
// add another "one shot" event handler
queue.Add((sender, e) => Console.WriteLine(e));
test.Start();
Code:
class OneShotHandlerQueue<TEventArgs> where TEventArgs : EventArgs {
private ConcurrentQueue<EventHandler<TEventArgs>> queue;
public OneShotHandlerQueue() {
this.queue = new ConcurrentQueue<EventHandler<TEventArgs>>();
}
public void Handle(object sender, TEventArgs e) {
EventHandler<TEventArgs> handler;
if (this.queue.TryDequeue(out handler) && (handler != null))
handler(sender, e);
}
public void Add(EventHandler<TEventArgs> handler) {
this.queue.Enqueue(handler);
}
}
Test class:
class Test {
public event EventHandler Done;
public void Start() {
this.OnDone(new EventArgs());
}
protected virtual void OnDone(EventArgs e) {
EventHandler handler = this.Done;
if (handler != null)
handler(this, e);
}
}
You can use reflection:
public static class Listener {
public static void ListenOnce(this object eventSource, string eventName, EventHandler handler) {
var eventInfo = eventSource.GetType().GetEvent(eventName);
EventHandler internalHandler = null;
internalHandler = (src, args) => {
eventInfo.RemoveEventHandler(eventSource, internalHandler);
handler(src, args);
};
eventInfo.AddEventHandler(eventSource, internalHandler);
}
public static void ListenOnce<TEventArgs>(this object eventSource, string eventName, EventHandler<TEventArgs> handler) where TEventArgs : EventArgs {
var eventInfo = eventSource.GetType().GetEvent(eventName);
EventHandler<TEventArgs> internalHandler = null;
internalHandler = (src, args) => {
eventInfo.RemoveEventHandler(eventSource, internalHandler);
handler(src, args);
};
eventInfo.AddEventHandler(eventSource, internalHandler);
}
}
Use it like so:
variableOfSomeType.ListenOnce("SomeEvent",
(s, args) => Console.WriteLine("I should print only once!"));
variableOfSomeType.ListenOnce<InterestingEventArgs>("SomeOtherEvent",
(s, args) => Console.WriteLine("I should print only once!"));
If you can use the Reactive Extensions for .NET, you can simplify this.
You can make an Observable from an event, and only listen for the first element using .Take(1), to do your small snippet of code. This turns this entire process into a couple of lines of code.
Edit: In order to demonstrate, I've made a full sample program (I'll paste below).
I moved the observable creation and subscription into a method (HandleOneShot). This lets you do what you're attempting with a single method call. For demonstrating, I made a class with two properties that implements INotifyPropertyChanged, and am listening for the first property changed event, writing to the console when it occurs.
This takes your code, and changes it to:
HandleOneShot<SomeEventArgs>(variableOfSomeType, "SomeEvent", e => {
// Small snippet of code here
});
Notice that all of the subscription/unsubscription happens automatically for you behind the scenes. There's no need to handle putting in the subscription manually - just Subscribe to the Observable, and Rx takes care of this for you.
When run, this code prints:
Setup...
Setting first property...
**** Prop2 Changed! /new val
Setting second property...
Setting first property again.
Press ENTER to continue...
You only get a single, one shot trigger of your event.
namespace ConsoleApplication1
{
using System;
using System.ComponentModel;
using System.Linq;
class Test : INotifyPropertyChanged
{
private string prop2;
private string prop;
public string Prop
{
get {
return prop;
}
set
{
if (prop != value)
{
prop = value;
if (PropertyChanged!=null)
PropertyChanged(this, new PropertyChangedEventArgs("Prop"));
}
}
}
public string Prop2
{
get
{
return prop2;
}
set
{
if (prop2 != value)
{
prop2 = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Prop2"));
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
class Program
{
static void HandleOneShot<TEventArgs>(object target, string eventName, Action<TEventArgs> action) where TEventArgs : EventArgs
{
var obsEvent = Observable.FromEvent<TEventArgs>(target, eventName).Take(1);
obsEvent.Subscribe(a => action(a.EventArgs));
}
static void Main(string[] args)
{
Test test = new Test();
Console.WriteLine("Setup...");
HandleOneShot<PropertyChangedEventArgs>(
test,
"PropertyChanged",
e =>
{
Console.WriteLine(" **** {0} Changed! {1}/{2}!", e.PropertyName, test.Prop, test.Prop2);
});
Console.WriteLine("Setting first property...");
test.Prop2 = "new value";
Console.WriteLine("Setting second property...");
test.Prop = "second value";
Console.WriteLine("Setting first property again...");
test.Prop2 = "other value";
Console.WriteLine("Press ENTER to continue...");
Console.ReadLine();
}
}
}
Another user encountered a very similar problem, and I believe the solution in that thread applies here.
In particular, what you have is not an instance of the publish/subscribe pattern, its a message queue. Its easy enough to create your own message queue using a Queue{EventHandler}, where you dequeue events as you invoke them.
So instead of hooking on to an event handler, your "one-shot" events should expose a method allowing clients to add an function to the message queue.
Does it work? If so, then I say go for it. For a one-shot event that looks to be quite elegant.
What I like...
If s is garbage collected, so will the event handler.
The detaching code is right next to the attaching code, making it easy to see what you are are doing.
You might be able to generalize it, but I'm not entierly sure how to because I can't seem to get a pointer to a event.
Personally, I just create a specialized extension method for whatever type has the event I'm dealing with.
Here's a basic version of something I am using right now:
namespace MyLibrary
{
public static class FrameworkElementExtensions
{
public static void HandleWhenLoaded(this FrameworkElement el, RoutedEventHandler handler)
{
RoutedEventHandler wrapperHandler = null;
wrapperHandler = delegate
{
el.Loaded -= wrapperHandler;
handler(el, null);
};
el.Loaded += wrapperHandler;
}
}
}
The reason I think this is the best solution is because you often don't need to just handle the event one time. You also often need to check if the event has already passed... For instance, here is another version of the above extension method that uses an attached property to check if the element is already loaded, in which case it just calls the given handler right away:
namespace MyLibraryOrApplication
{
public static class FrameworkElementExtensions
{
public static void HandleWhenLoaded(this FrameworkElement el, RoutedEventHandler handler)
{
if ((bool)el.GetValue(View.IsLoadedProperty))
{
// el already loaded, call the handler now.
handler(el, null);
return;
}
// el not loaded yet. Attach a wrapper handler that can be removed upon execution.
RoutedEventHandler wrapperHandler = null;
wrapperHandler = delegate
{
el.Loaded -= wrapperHandler;
el.SetValue(View.IsLoadedProperty, true);
handler(el, null);
};
el.Loaded += wrapperHandler;
}
}
}
You probably want to work with the new async/await idioms.
Usually when I need to execute an event handler one-shot like you described, what I really need is something like:
await variableOfSomeSort.SomeMethodAsync();
//small snippet of code here
Why not do use the delegate stack built into the event?
Something like...
private void OnCheckedIn(object sender, Session e)
{
EventHandler<Session> nextInLine = null;
lock (_syncLock)
{
if (SessionCheckedIn != null)
{
nextInLine = (EventHandler<Session>)SessionCheckedIn.GetInvocationList()[0];
SessionCheckedIn -= nextInLine;
}
}
if ( nextInLine != null )
{
nextInLine(this, e);
}
}

Unsubscribe anonymous method in C#

Is it possible to unsubscribe an anonymous method from an event?
If I subscribe to an event like this:
void MyMethod()
{
Console.WriteLine("I did it!");
}
MyEvent += MyMethod;
I can un-subscribe like this:
MyEvent -= MyMethod;
But if I subscribe using an anonymous method:
MyEvent += delegate(){Console.WriteLine("I did it!");};
is it possible to unsubscribe this anonymous method? If so, how?
Action myDelegate = delegate(){Console.WriteLine("I did it!");};
MyEvent += myDelegate;
// .... later
MyEvent -= myDelegate;
Just keep a reference to the delegate around.
One technique is to declare a variable to hold the anonymous method which would then be available inside the anonymous method itself. This worked for me because the desired behavior was to unsubscribe after the event was handled.
Example:
MyEventHandler foo = null;
foo = delegate(object s, MyEventArgs ev)
{
Console.WriteLine("I did it!");
MyEvent -= foo;
};
MyEvent += foo;
Since C# 7.0 local functions feature has been released, the approach suggested by J c becomes really neat.
void foo(object s, MyEventArgs ev)
{
Console.WriteLine("I did it!");
MyEvent -= foo;
};
MyEvent += foo;
So, honestly, you do not have an anonymous function as a variable here. But I suppose the motivation to use it in your case can be applied to local functions.
From memory, the specification explicitly doesn't guarantee the behaviour either way when it comes to equivalence of delegates created with anonymous methods.
If you need to unsubscribe, you should either use a "normal" method or retain the delegate somewhere else so you can unsubscribe with exactly the same delegate you used to subscribe.
In 3.0 can be shortened to:
MyHandler myDelegate = ()=>Console.WriteLine("I did it!");
MyEvent += myDelegate;
...
MyEvent -= myDelegate;
Instead of keeping a reference to any delegate you can instrument your class in order to give the event's invocation list back to the caller. Basically you can write something like this (assuming that MyEvent is declared inside MyClass):
public class MyClass
{
public event EventHandler MyEvent;
public IEnumerable<EventHandler> GetMyEventHandlers()
{
return from d in MyEvent.GetInvocationList()
select (EventHandler)d;
}
}
So you can access the whole invocation list from outside MyClass and unsubscribe any handler you want. For instance:
myClass.MyEvent -= myClass.GetMyEventHandlers().Last();
I've written a full post about this tecnique here.
Kind of lame approach:
public class SomeClass
{
private readonly IList<Action> _eventList = new List<Action>();
...
public event Action OnDoSomething
{
add {
_eventList.Add(value);
}
remove {
_eventList.Remove(value);
}
}
}
Override the event add/remove methods.
Keep a list of those event handlers.
When needed, clear them all and re-add the others.
This may not work or be the most efficient method, but should get the job done.
If you want to be able to control unsubscription then you need to go the route indicated in your accepted answer. However, if you are just concerned about clearing up references when your subscribing class goes out of scope, then there is another (slightly convoluted) solution which involves using weak references. I've just posted a question and answer on this topic.
One simple solution:
just pass the eventhandle variable as parameter to itself.
Event if you have the case that you cannot access the original created variable because of multithreading, you can use this:
MyEventHandler foo = null;
foo = (s, ev, mehi) => MyMethod(s, ev, foo);
MyEvent += foo;
void MyMethod(object s, MyEventArgs ev, MyEventHandler myEventHandlerInstance)
{
MyEvent -= myEventHandlerInstance;
Console.WriteLine("I did it!");
}
If the best way is to keep a reference on the subscribed eventHandler, this can be achieved using a Dictionary.
In this example, I have to use a anonymous method to include the mergeColumn parameter for a set of DataGridViews.
Using the MergeColumn method with the enable parameter set to true enables the event while using it with false disables it.
static Dictionary<DataGridView, PaintEventHandler> subscriptions = new Dictionary<DataGridView, PaintEventHandler>();
public static void MergeColumns(this DataGridView dg, bool enable, params ColumnGroup[] mergedColumns) {
if(enable) {
subscriptions[dg] = (s, e) => Dg_Paint(s, e, mergedColumns);
dg.Paint += subscriptions[dg];
}
else {
if(subscriptions.ContainsKey(dg)) {
dg.Paint -= subscriptions[dg];
subscriptions.Remove(dg);
}
}
}
if you want refer to some object with this delegate, may be you can use Delegate.CreateDelegate(Type, Object target, MethodInfo methodInfo)
.net consider the delegate equals by target and methodInfo
There is a way to solve this by implementing the closure yourself instead of a lambda expression.
Assume that the class to be used as a capture variable is as follows.
public class A
{
public void DoSomething()
{
...
}
}
public class B
{
public void DoSomething()
{
...
}
}
public class C
{
public void DoSomething()
{
...
}
}
These classes will be used as capture variables, so we instantiate them.
A a = new A();
B b = new B();
C c = new C();
Implement the closure class as shown below.
private class EventHandlerClosure
{
public A a;
public B b;
public C c;
public event EventHandler Finished;
public void MyMethod(object, MyEventArgs args)
{
a.DoSomething();
b.DoSomething();
c.DoSomething();
Console.WriteLine("I did it!");
Finished?.Invoke(this, EventArgs.Empty);
}
}
Instantiate the closure class, create a handler, then subscribe to the event and subscribe to the lambda expression that unsubscribes from the closure class's Finished event.
var closure = new EventHandlerClosure
{
a = a,
b = b,
c = c
};
var handler = new MyEventHandler(closure.MyMethod);
MyEvent += handler;
closure.Finished += (s, e)
{
MyEvent -= handler;
}
I discovered this quite old thread recently for a C# project and found all the answers very useful. However, there was one aspect that didn't work well for my particular use case - they all put the burden of unsubscribing from an event on the subscriber. I understand that one could make the argument that it's the subscribers job to handle this, however that isn't realistic for my project.
My primary use case for events is for listening to timers to sequence animations (it's a game). In this scenario, I use a lot of anonymous delegates to chain together sequences. Storing a reference to these isn't very practical.
In order to solve this, I've created a wrapper class around an event that lets you subscribe for a single invocation.
internal class EventWrapper<TEventArgs> {
private event EventHandler<TEventArgs> Event;
private readonly HashSet<EventHandler<TEventArgs>> _subscribeOnces;
internal EventWrapper() {
_subscribeOnces = new HashSet<EventHandler<TEventArgs>>();
}
internal void Subscribe(EventHandler<TEventArgs> eventHandler) {
Event += eventHandler;
}
internal void SubscribeOnce(EventHandler<TEventArgs> eventHandler) {
_subscribeOnces.Add(eventHandler);
Event += eventHandler;
}
internal void Unsubscribe(EventHandler<TEventArgs> eventHandler) {
Event -= eventHandler;
}
internal void UnsubscribeAll() {
foreach (EventHandler<TEventArgs> eventHandler in Event?.GetInvocationList()) {
Event -= eventHandler;
}
}
internal void Invoke(Object sender, TEventArgs e) {
Event?.Invoke(sender, e);
if(_subscribeOnces.Count > 0) {
foreach (EventHandler<TEventArgs> eventHandler in _subscribeOnces) {
Event -= eventHandler;
}
_subscribeOnces.Clear();
}
}
internal void Remove() {
UnsubscribeAll();
_subscribeOnces.Clear();
}
}
The side benefit of having this in a class is that you can make it private and expose only the functionality you want. For example, only expose the SubscribeOnce (and not the Subscribe) method.
public class MyClass {
private EventWrapper<MyEventEventArgs> myEvent = new EventWrapper<MyEventEventArgs>();
public void FireMyEvent() {
myEvent.Invoke(this, new MyEventEventArgs(1000, DateTime.Now));
}
public void SubscribeOnce(EventHandler<MyEventEventArgs> eventHandler) {
myEvent.SubscribeOnce(eventHandler);
}
public class MyEventEventArgs : EventArgs {
public int MyInt;
public DateTime MyDateTime;
public MyEventEventArgs(int myInt, DateTime myDateTime) {
MyInt = myInt;
MyDateTime = myDateTime;
}
}
}
The tradeoff here is more overhead for having an instance of this for each event, however in my scenario - this is an acceptable tradeoff to ensure that garbage gets collected efficiently and the code is more maintainable on the subscriber side. Full example here.
Here is a simple solution, which removes all assigned methods from an event. Also anonymous methods.
Use this code and adjust the names.
if (MyEvent != null)
foreach (Delegate del in MyEvent.GetInvocationList())
MyEvent -= (EventHandler<MyEventHandlerType>)del;
Example usage
public class SomeClass
{
public event EventHandler<NiceEventArgs> NiceEvent;
public void RemoveHandlers()
{
if (NiceEvent != null)
foreach (Delegate del in NiceEvent.GetInvocationList())
NiceEvent -= (EventHandler<NiceEventArgs>)del;
}
}
Thanks to hemme's answer, which I used as inspiration.

Categories