C# Advanced: Subscribing to Events
mohamed Tayel
Posted on October 12, 2024
Meta Description:
Learn how to handle events in C# using a stock management system example. This article covers the fundamentals of subscribing to events, providing practical examples and assignments at various difficulty levels.
Introduction
Events in C# provide an efficient way for objects to communicate without being tightly coupled. They follow the publish-subscribe pattern, where one object (the publisher) notifies other objects (subscribers) when a specific action occurs. In this article, we’ll walk through a practical example of event handling using a stock management system and provide assignments to help you apply the concept at various difficulty levels.
1. What Are Events in C#?
Events in C# are built on delegates and allow for flexible communication between objects. They are particularly useful in scenarios where one object needs to notify other objects that something important has happened.
In our stock management example, the system will notify subscribers when stock levels fall below a certain threshold, triggering actions like restocking and notifying the supplier.
2. Stock Management System Example
Let’s build a simple stock management system that monitors product inventory. When the stock of an item falls below a certain level (5 units), it triggers an event to notify the WarehouseManager
and SupplierService
to take action.
Step 1: Define the Event in the Inventory Manager
We will define a StockLow
event in the InventoryManager
class. This event is raised when the stock of an item drops below 5 units.
using System;
public class StockEventArgs : EventArgs
{
public string ItemName { get; set; }
public int CurrentStock { get; set; }
}
public class InventoryManager
{
public event EventHandler<StockEventArgs> StockLow;
private int _stockLevel;
public string ItemName { get; set; }
public InventoryManager(string itemName, int initialStock)
{
ItemName = itemName;
_stockLevel = initialStock;
}
public void ProcessSale(int quantity)
{
_stockLevel -= quantity;
Console.WriteLine($"{quantity} {ItemName}(s) sold. Current stock: {_stockLevel}");
if (_stockLevel < 5)
{
OnStockLow();
}
}
protected virtual void OnStockLow()
{
StockLow?.Invoke(this, new StockEventArgs { ItemName = this.ItemName, CurrentStock = this._stockLevel });
}
}
Explanation:
- The
InventoryManager
class tracks the stock of a product. - The
StockLow
event is triggered when the stock falls below the threshold of 5 units. - The
StockEventArgs
class is used to pass the item name and current stock to the event subscribers.
Step 2: Subscribe to the Event
Next, we create a WarehouseManager
and a SupplierService
, both of which will subscribe to the StockLow
event. When the stock level falls below the threshold, they take appropriate actions such as restocking or notifying the supplier.
public class WarehouseManager
{
public void Restock(object sender, StockEventArgs e)
{
Console.WriteLine($"Warehouse notified: Restock {e.ItemName} (Current stock: {e.CurrentStock})");
}
}
public class SupplierService
{
public void NotifySupplier(object sender, StockEventArgs e)
{
Console.WriteLine($"Supplier notified to replenish stock for {e.ItemName}.");
}
}
public class Program
{
public static void Main(string[] args)
{
InventoryManager inventory = new InventoryManager("Laptop", 10);
WarehouseManager warehouse = new WarehouseManager();
SupplierService supplier = new SupplierService();
// Subscribe to the StockLow event
inventory.StockLow += warehouse.Restock;
inventory.StockLow += supplier.NotifySupplier;
// Simulate sales that reduce stock
inventory.ProcessSale(3); // Stock = 7, no event triggered
inventory.ProcessSale(4); // Stock = 3, event triggered
}
}
Explanation:
- The
WarehouseManager
andSupplierService
subscribe to theStockLow
event. - When the stock drops below 5, both subscribers are notified, and actions are triggered (restocking and supplier notification).
3. How Events Work in This System
In this stock management system, the InventoryManager
acts as the publisher. When the stock level falls below a certain threshold, it raises the StockLow
event. The WarehouseManager
and SupplierService
are subscribers that respond to the event by restocking and notifying suppliers.
Publisher: InventoryManager
- Raises the
StockLow
event when stock levels drop.
Subscribers: WarehouseManager
and SupplierService
- Handle the event by performing actions like restocking and notifying suppliers.
4. Important Event Patterns in C#
Here are some best practices to keep in mind when working with events in C#:
-
Use
EventHandler
: Always useEventHandler
orEventHandler<T>
to follow C# conventions for event signatures. - Unsubscribe from Events: Ensure that subscribers properly unsubscribe from events when no longer needed to avoid memory leaks.
- Sequential Execution: Event handlers are executed in the order they were added unless explicitly handled asynchronously.
Full Code: Stock Management System Using Events in C
using System;
public class StockEventArgs : EventArgs
{
public string ItemName { get; set; }
public int CurrentStock { get; set; }
}
public class InventoryManager
{
public event EventHandler<StockEventArgs> StockLow;
private int _stockLevel;
public string ItemName { get; set; }
public InventoryManager(string itemName, int initialStock)
{
ItemName = itemName;
_stockLevel = initialStock;
}
public void ProcessSale(int quantity)
{
_stockLevel -= quantity;
Console.WriteLine($"{quantity} {ItemName}(s) sold. Current stock: {_stockLevel}");
if (_stockLevel < 5)
{
OnStockLow();
}
}
protected virtual void OnStockLow()
{
StockLow?.Invoke(this, new StockEventArgs { ItemName = this.ItemName, CurrentStock = this._stockLevel });
}
}
public class WarehouseManager
{
public void Restock(object sender, StockEventArgs e)
{
Console.WriteLine($"Warehouse notified: Restock {e.ItemName} (Current stock: {e.CurrentStock})");
}
}
public class SupplierService
{
public void NotifySupplier(object sender, StockEventArgs e)
{
Console.WriteLine($"Supplier notified to replenish stock for {e.ItemName}.");
}
}
public class Program
{
public static void Main(string[] args)
{
InventoryManager inventory = new InventoryManager("Laptop", 10);
WarehouseManager warehouse = new WarehouseManager();
SupplierService supplier = new SupplierService();
// Subscribe to the StockLow event
inventory.StockLow += warehouse.Restock;
inventory.StockLow += supplier.NotifySupplier;
// Simulate sales that reduce stock
inventory.ProcessSale(3); // Stock = 7, no event triggered
inventory.ProcessSale(4); // Stock = 3, event triggered
}
}
5. Assignments to Practice Events in C#
Here are three assignments to help you apply what you’ve learned:
Easy Level:
Modify the InventoryManager
class to raise a new event called StockFull
when the stock goes above 50 units after a restock. Subscribe to this event in both the WarehouseManager
and SupplierService
classes.
Hint: Define and raise the StockFull
event similarly to the StockLow
event.
Medium Level:
Modify the program to track multiple products in the InventoryManager
. Create instances for "Laptops" and "Tablets," each with its own stock level. Ensure both can independently trigger stock alerts.
Hint: Use a list or dictionary to manage different products and their stock levels.
Difficult Level:
Make event handling asynchronous. Modify the OnStockLow
method to execute event handlers asynchronously using Task.Run
. Simulate delays in the Restock
and NotifySupplier
methods using Task.Delay()
to mimic real-world processing times.
Hint: Use async
and await
to handle tasks concurrently.
Conclusion
Events are a key mechanism for enabling communication between different parts of your application. They allow for loose coupling between components, making your code easier to maintain and extend. The stock management system example provides a clear illustration of how to use events effectively in C#. By completing the provided assignments, you will gain hands-on experience and a deeper understanding of event handling in real-world scenarios.
Posted on October 12, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.