|
||
---|---|---|
EonaCat.EventKit | ||
.gitignore | ||
EonaCat.EventKit.sln | ||
LICENSE | ||
README.md | ||
icon.png |
README.md
🎯 EonaCat.EventKit - The Ultimate C# Event Management Toolkit
EonaCat.EventKit
is a hybrid runtime + Roslyn analyzer library
that makes subscribing/unsubscribing and managing events safer, smarter, and simpler.
🚀 Features
✅ Runtime API
- 🔄 Subscribe/Unsubscribe to any event dynamically
- 🌐 Subscribe to all events of a class with optional filtering
- 🛡️ Reentrancy-safe handlers
- 💥 Safe execution with built-in exception handling
- 📖 Track current subscriptions
- 🔎 Event forwarding for diagnostics/logging
- 🧹 Automatic unsubscription on disposal
- 🧠 Weak event subscriptions for better memory management
- ⏳ Event expiry for timed unsubscription
- 🔄 Retry event handling for transient errors
- 🔥 Concurrent event handling for async operations
🧠 Roslyn Analyzers
- ⚠️ Detect duplicate subscriptions
- 🧹 Detect missing unsubscriptions
- 🔧 CodeFix: auto-insert
-=
for unsubscribing
📦 Installation
Install via NuGet:
dotnet add package EonaCat.EventKit
🛠️ Usage Example
Simple Event Subscription
var button = new Button();
EonaCat.EventKit.EventSubscriptionManager.Subscribe(button, "Click", (name, args) =>
{
Console.WriteLine($"Clicked: {args}");
});
// Later
EonaCat.EventKit.EventSubscriptionManager.Unsubscribe(button, "Click");
Subscribe All Events With Filter
EonaCat.EventKit.EventSubscriptionManager.SubscribeAll(
someControl,
evt => evt.Name.StartsWith("On"),
(name, args) => Console.WriteLine($"{name} fired!")
);
Concurrent Event Handling
EonaCat.EventKit.EventSubscriptionManager.SubscribeConcurrently(
someControl,
"Click",
async (name, args) =>
{
await SomeAsyncMethod();
Console.WriteLine($"{name} clicked asynchronously.");
});
Event Subscription with Expiry
EonaCat.EventKit.EventSubscriptionManager.SubscribeWithExpiry(
someControl,
"Click",
(name, args) =>
{
Console.WriteLine($"{name} clicked.");
},
TimeSpan.FromSeconds(30) // Expire the subscription after 30 seconds
);
Auto Unsubscribe on Dispose
EonaCat.EventKit.EventSubscriptionManager.SubscribeWithAutoUnsubscribeOnDispose(
someControl,
"Click",
(name, args) =>
{
Console.WriteLine($"{name} clicked.");
});
🛠️ Advanced Usage
Subscribe with Event Count Logging
EonaCat.EventKit.EventSubscriptionManager.SubscribeWithCountLogging(
someControl,
"Click",
(name, args) =>
{
Console.WriteLine($"{name} clicked.");
});
Retry Logic for Event Handling
EonaCat.EventKit.EventSubscriptionManager.SubscribeWithRetry(
someControl,
"Click",
(name, args) =>
{
Console.WriteLine($"{name} clicked.");
});
Subscribe with Execution Context (Thread-Safe)
EonaCat.EventKit.EventSubscriptionManager.SubscribeWithExecutionContext(
someControl,
"Click",
(name, args) =>
{
Console.WriteLine($"{name} clicked.");
});
🔎 Using the EventSubscriptionLogger
The EventSubscriptionLogger is a useful tool for tracking and logging event subscriptions. This can help you understand the flow of event subscriptions and ensure that everything is behaving as expected.
Enabling Event Subscription Logging
To enable event subscription logging, use the EventSubscriptionLogger in combination with EventSubscriptionManager to log all subscriptions and unsubscriptions.
// Enable event subscription logging
EonaCat.EventKit.EventSubscriptionLogger.Enable();
// Subscribe to an event
var button = new Button();
EonaCat.EventKit.EventSubscriptionManager.Subscribe(button, "Click", (name, args) =>
{
Console.WriteLine($"Clicked: {args}");
});
// Later, unsubscribe from the event
EonaCat.EventKit.EventSubscriptionManager.Unsubscribe(button, "Click");
// Disable event subscription logging (optional)
EonaCat.EventKit.EventSubscriptionLogger.Disable();
Custom Event Subscription Logger
You can also create a custom logger to output the subscription information in a way that fits your needs
EonaCat.EventKit.EventSubscriptionLogger.Enable(log =>
{
// Do custom logging action: For example, log to a file or console
Console.WriteLine($"Event subscribed: {log.EventName} to {log.Target}");
});
👀 Analyzer Diagnostics
ID | TITLE | FIX |
---|---|---|
EVT001 | Duplicate event subscription | Suggest review |
EVT002 | Missing event unsubscription | Auto-fix in code |
🧹 Memory Management Features
- 🧹 Automatic unsubscription on disposal to prevent memory leaks.
- 🧠 Weak event subscriptions to help with garbage collection.
- ⏳ Event expiry to automatically unsubscribe after a specified duration.
- 🔄 Retry logic for transient errors during event handling.
- 🔥 Concurrent event handling for async operations.
- 🧠 Weak event subscriptions to prevent memory leaks when the target object is no longer referenced.
- 💡 Reentrancy-safe handling to avoid recursive event triggering during handler execution.
⚙️ Customization Options
SubscribeOptions
- ReentrancySafe : Ensures handlers aren't invoked while already executing for the same event.
- UseWeakReference: Enables weak references for event subscriptions to help with garbage collection.
- HandleExceptions: Configures whether exceptions in event handlers should be logged or handled silently.
Example
EonaCat.EventKit.EventSubscriptionManager.Subscribe(
someControl,
"Click",
(name, args) =>
{
Console.WriteLine($"Clicked: {args}");
},
new SubscribeOptions { ReentrancySafe = true, UseWeakReference = true });
🧑💻 Subscribing to Events in Regular Classes
EonaCat.EventKit isn't limited to UI controls; you can subscribe to events in regular classes that define events as well.
Example with a Custom Class (Non-Control) Let’s create a class MyCustomClass that has a few events. We'll use the source generator to generate subscription and unsubscription methods, and then use them in the same way.
Step 1: Define a Custom Class with Events
public class MyCustomClass
{
// Define events
public event EventHandler SomeEvent;
public event EventHandler<string> MessageEvent;
// Methods to fire events
public void TriggerSomeEvent()
{
SomeEvent?.Invoke(this, EventArgs.Empty);
}
public void TriggerMessageEvent(string message)
{
MessageEvent?.Invoke(this, message);
}
}
Step 2: Generated Subscription Code After running the EventSubscriptionSourceGenerator, you would get a generated class MyCustomClassEventSubscriptions, which will contain the subscription and unsubscription methods. Here's what the generated code would look like:
namespace GeneratedEventSubscriptions
{
public static class MyCustomClassEventSubscriptions
{
public static void Subscribe()
{
// Subscribing to events
EonaCat.EventKit.EventSubscriptionManager.SubscribeWeak(MyCustomClass.Instance, "SomeEvent", GeneratedEventHandler_SomeEventHandler);
EonaCat.EventKit.EventSubscriptionManager.SubscribeWeak(MyCustomClass.Instance, "MessageEvent", GeneratedEventHandler_MessageEventHandler);
}
public static void Unsubscribe()
{
// Unsubscribing from events
EonaCat.EventKit.EventSubscriptionManager.Unsubscribe(MyCustomClass.Instance, "SomeEvent");
EonaCat.EventKit.EventSubscriptionManager.Unsubscribe(MyCustomClass.Instance, "MessageEvent");
}
// Event Handlers
private static void GeneratedEventHandler_SomeEventHandler(object sender, EventArgs args)
{
Console.WriteLine("SomeEvent triggered.");
}
private static void GeneratedEventHandler_MessageEventHandler(object sender, string message)
{
Console.WriteLine($"MessageEvent triggered with message: {message}");
}
}
}
Step 3: Using the Subscription and Unsubscription in Code Now, you can use the generated subscription and unsubscription methods just like before but with a regular class instead of a control. Here’s how to use it in your program:
using System;
using GeneratedEventSubscriptions; // Import the generated namespace
class Program
{
static void Main(string[] args)
{
// Create instance of the custom class
var myClass = new MyCustomClass();
// Subscribe to events
MyCustomClassEventSubscriptions.Subscribe();
// Trigger events
myClass.TriggerSomeEvent(); // Should trigger SomeEvent handler
myClass.TriggerMessageEvent("Hello, World!"); // Should trigger MessageEvent handler
// Optionally, unsubscribe from events
MyCustomClassEventSubscriptions.Unsubscribe();
// Trigger events again after unsubscription (no output as it is unsubscribed)
myClass.TriggerSomeEvent();
myClass.TriggerMessageEvent("Goodbye!"); // No output
}
}
🔄 Conclusion
EonaCat.EventKit offers a flexible and powerful event management toolkit that works seamlessly with both UI controls and regular classes. Whether you're handling events in UI elements or business logic classes, the toolkit provides robust features like subscription management, weak references, automatic unsubscription, and even retry logic for transient errors.