Weak Delegates for .NET
While there are many systems out there for weak events/delegates in .NET they
generally suffer from one or more of the following flaws:
System.EventHander
and System.EventHander<T>
.Not liking these issue I’ve created this experiment repository where I can try
create a system that has none of those issues. Currently issue #1 is completely
solved, this system with work with any delegate type. Issue #2 is mostly there,
though there is work to be done. Issue #3 is sadly still unsolved.
namespace WeakDelegates
{
// Usage is the same as System.Delegate.Combine(Delegate, Delegate);
public static T Combine<T>(T a, T b) where T : class;
// Usage is the same as System.Delegate.Remove(Delegate, Delegate);
public static T Remove<T>(T source, T value) where T : class;
// Allows removing weak delegates when you don't have access to the delegate field directly.
public static void Remove<T>(object eventContainer, string eventName, T value) where T : class
}
Documentation for the same named static methods on System.Delegate
should be
the same. Only real difference is that I use generics and enforce that it must
be a delegate type at run-time instead of forcing you to do lots of casting.
The Remove<T>(object eventContainer, string eventName, T value) where T :
class
method can be used to unsubscribe weak delegates from events.
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using static System.Collections.Specialized.WeakDelegateHelpers;
namespace WeakTest
{
class Program
{
private class TestClass
{
private DateTime created = DateTime.UtcNow;
public void Handle(object sender, NotifyCollectionChangedEventArgs e)
{
Console.WriteLine(e.NewItems[0]);
}
}
public static void Main()
{
ObservableCollection<int> collection = new ObservableCollection<int>();
TestClass testInstance = new TestClass();
// To subscribe
collection.CollectionChanged += WeakDelegates.WeakDelegate.Combine<NotifyCollectionChangedEventHandler>(null, testInstance.Handle);
// to unsubscribe
WeakDelegates.WeakDelegate.Remove<NotifyCollectionChangedEventHandler>(collection, nameof(collection.CollectionChanged), testInstance.Handle);
}
}
}
See The Problem With
Delegates
by Dustin Campbell.