Scotec.Events.WeakEvents 1.1.1-dev.12

This is a prerelease version of Scotec.Events.WeakEvents.
dotnet add package Scotec.Events.WeakEvents --version 1.1.1-dev.12
                    
NuGet\Install-Package Scotec.Events.WeakEvents -Version 1.1.1-dev.12
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Scotec.Events.WeakEvents" Version="1.1.1-dev.12" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Scotec.Events.WeakEvents" Version="1.1.1-dev.12" />
                    
Directory.Packages.props
<PackageReference Include="Scotec.Events.WeakEvents" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Scotec.Events.WeakEvents --version 1.1.1-dev.12
                    
#r "nuget: Scotec.Events.WeakEvents, 1.1.1-dev.12"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Scotec.Events.WeakEvents@1.1.1-dev.12
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Scotec.Events.WeakEvents&version=1.1.1-dev.12&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Scotec.Events.WeakEvents&version=1.1.1-dev.12&prerelease
                    
Install as a Cake Tool

WeakEventManager

The WeakEventManager class in the Scotec.Events.WeakEvents namespace provides a thread-safe mechanism for managing event subscriptions using weak references. This helps prevent memory leaks that can occur when event handlers are strongly referenced, especially in scenarios where publishers outlive their subscribers.

Purpose

In .NET, traditional event subscriptions create strong references between the event source and the event handler. If the subscriber is not explicitly unsubscribed, the event source will keep the subscriber alive, potentially causing memory leaks. WeakEventManager solves this by storing event handlers as weak references, allowing the garbage collector to reclaim subscribers when they are no longer in use.

Features

  • Add weak event handlers for any event on any object.
  • Remove weak event handlers manually or automatically when the target is collected.
  • Automatic cleanup of dead handlers.
  • Thread-safe management of event handler delegates.
  • Disposable remover for easy unsubscription.
  • Static API for global weak event management.

Usage

1. Adding a Weak Event Handler (Instance)

Subscribe to an event using a weak reference:

var manager = new WeakEventManager(); 
IDisposable remover = manager.AddWeakHandler<MySource, MyEventArgs>( sourceObject, "MyEvent", (src, args) => { /* handle event */ } );
  • sourceObject: The object that publishes the event.
  • "MyEvent": The name of the event to subscribe to.
  • Handler: A lambda or method matching (src, args).

2. Removing a Weak Event Handler

You can remove a handler using the returned IDisposable:

remover.Dispose();

Or, remove it directly:

manager.RemoveWeakHandler<MySource, MyEventArgs>( sourceObject, "MyEvent", handler );

3. Cleaning Up Dead Handlers

To remove handlers whose targets have been garbage collected:

manager.Cleanup();

This can be useful to call periodically, for example, in an Application.Deactivated event or similar global pause event, to ensure that any unused handlers are removed, and memory can be reclaimed.

manager.CleanupDeadHandlers();

4. Disposing the Manager

Dispose the manager to remove all handlers and clean up resources:

manager.Dispose();

5. Static Usage

For global event management, use the static API:

WeakEventManager.AddWeakHandler<MySource, MyEventArgs>( sourceObject, "MyEvent", (src, args) => { /* handle event */ } );

API Reference

  • AddWeakHandler<TObject, TEventArgs>(TObject source, string eventName, Action<TObject, TEventArgs> handler): Registers a weak event handler and returns an IDisposable for manual removal.
  • RemoveWeakHandler<TObject, TEventArgs>(TObject source, string eventName, Action<TObject, TEventArgs> handler): Removes a previously registered weak event handler.
  • CleanupDeadHandlers(): Removes handlers whose targets have been garbage collected.
  • Dispose(): Removes all handlers and releases resources.

Example

public class MySource 
{ 
    public event EventHandler<MyEventArgs> MyEvent; 
}

public class MySubscriber 
{ 
    public void Subscribe(MySource source, WeakEventManager manager) 
    { 
        manager.AddWeakHandler<MySource, MyEventArgs>( source, nameof(source.MyEvent), (src, args) => HandleEvent(args) ); 
    }
    private void HandleEvent(MySource source, MyEventArgs args)
    {
        // Handle event logic
    }
}

When to Use

  • To avoid memory leaks from event subscriptions.
  • In MVVM, UI, or long-lived publisher scenarios.
  • When subscribers may be short-lived or dynamically created.

Notes

  • The event name must match the actual event on the source object.
  • Only events with compatible delegate signatures are supported.
  • The manager is thread-safe.
  • Compatible with .NET Standard 2.0 and 2.1.

License

See LICENSE for details.


For more information, see the source code in Scotec.Events.WeakEvents\WeakEventManager.cs

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 is compatible. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.
  • .NETStandard 2.1

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Scotec.Events.WeakEvents:

Package Downloads
Scotec.XmlDatabase

Wrapper for XML files that supports transactional operations.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.1-dev.12 172 11/27/2025
1.1.1-dev.11 147 11/25/2025
1.1.1-dev.10 139 11/25/2025
1.1.1-dev.9 138 11/25/2025
1.1.1-dev.5 251 11/21/2025
1.1.0 445 11/18/2025
1.0.9 450 11/18/2025
1.0.9-dev.15 186 9/22/2025
1.0.9-dev.13 151 8/30/2025
1.0.9-dev.10 66 7/19/2025
1.0.9-dev.8 138 7/17/2025
1.0.9-dev.6 141 7/16/2025
1.0.9-dev.5 141 7/16/2025
1.0.9-dev.4 140 7/16/2025
1.0.9-dev.3 144 7/16/2025
1.0.8 609 3/25/2025
1.0.8-dev.2 206 3/4/2025
1.0.8-dev.1 212 3/4/2025
1.0.7 238 1/24/2025
1.0.6 225 1/10/2025
1.0.5 218 1/10/2025
1.0.5-dev.6 104 12/26/2024
1.0.4 239 11/25/2024
1.0.3 311 9/13/2024
1.0.2-dev.5 130 9/13/2024
1.0.2-dev.4 117 9/13/2024
1.0.2-dev.3 110 9/13/2024
1.0.2-dev.2 129 9/13/2024
1.0.1 364 7/14/2024
1.0.1-dev.6 104 9/13/2024
1.0.1-dev.1 153 1/14/2024
1.0.0 877 1/1/2024
1.0.0-dev.28 120 1/1/2024
0.9.4-dev.23 124 12/29/2023
0.9.4-dev.20 168 11/9/2023
0.9.4-dev.15 124 9/28/2023
0.9.4-dev.14 113 9/28/2023
0.9.4-dev.9 127 9/23/2023
0.9.4-dev.8 127 9/22/2023
0.9.3 328 9/1/2023
0.9.3-dev.102 125 9/22/2023
0.9.3-dev.101 146 9/22/2023
0.9.3-dev.92 139 8/23/2023
0.9.3-dev.70 191 3/18/2023
0.9.3-dev.69 195 3/18/2023
0.9.3-dev.67 188 3/18/2023
0.9.3-dev.66 190 3/18/2023
0.9.3-dev.64 190 3/6/2023
0.9.3-dev.62 183 2/17/2023
0.9.3-dev.61 186 2/17/2023
0.9.3-dev.58 195 2/17/2023
0.9.3-dev.53 176 2/17/2023
0.9.3-dev.52 191 2/17/2023
0.9.3-dev.44 217 1/24/2023
0.9.3-dev.43 208 1/23/2023
0.9.3-dev.42 198 1/23/2023
0.9.3-dev.41 213 1/23/2023
0.9.3-dev.40 206 1/19/2023
0.9.3-dev.34 201 12/30/2022
0.9.3-dev.33 188 12/30/2022
0.9.3-dev.30 234 11/29/2022
0.9.3-dev.29 198 11/18/2022
0.9.3-dev.19 213 11/11/2022
0.9.3-dev.17 198 11/10/2022
0.9.2 623 10/24/2022
0.9.1 632 10/23/2022
0.9.0 671 10/20/2022
0.1.0 655 10/20/2022