Skip to content

Commit ae366ef

Browse files
committed
Generic event args types to handle common functionality
1 parent 30516f6 commit ae366ef

File tree

4 files changed

+82
-60
lines changed

4 files changed

+82
-60
lines changed

Yubico.Core/src/Yubico/Core/Devices/DeviceEventArgs.cs

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,30 +13,63 @@
1313
// limitations under the License.
1414

1515
using System;
16-
using System.Collections.Generic;
17-
using System.Text;
1816

1917
namespace Yubico.Core.Devices
2018
{
2119
/// <summary>
22-
/// Event arguments given whenever a device is added or removed from the system.
20+
/// Defines the contract for device-related event arguments in a generic context.
21+
/// This interface allows for type-safe access to device information in event handling
22+
/// scenarios, supporting various device types that implement the IDevice interface.
23+
/// It provides a flexible foundation for device event systems, enabling specific
24+
/// device type information to be preserved and accessed in event handlers.
2325
/// </summary>
24-
public class DeviceEventArgs : EventArgs
26+
/// <remarks>
27+
/// While this interface does not inherit from <see cref="System.EventArgs"/>, it retains the "Args" suffix
28+
/// in its name. This naming convention is deliberately chosen to maintain consistency with standard
29+
/// event argument naming patterns in C#, particularly for improved readability when used in delegate
30+
/// and event handler signatures. The familiar "Args" suffix clearly indicates the interface's role
31+
/// in event-related contexts, despite not directly extending EventArgs.
32+
/// </remarks>
33+
/// <typeparam name="TDevice">The specific type of <see cref="IDevice"/> this event argument represents.
34+
/// This type parameter is covariant, allowing for more specific device types to be used
35+
/// where a more general device type is expected.</typeparam>
36+
#pragma warning disable CA1711 // Identifiers should not have incorrect suffix
37+
public interface IDeviceEventArgs<out TDevice> where TDevice : IDevice
38+
#pragma warning restore CA1711 // Identifiers should not have incorrect suffix
2539
{
2640
/// <summary>
27-
/// The device that originated the event.
41+
/// Gets the specific type of <see cref="IDevice"/> that originated the event.
42+
/// This property will always be populated, regardless of whether this is an arrival event or a removal event.
43+
/// If the device was removed, not all members will be available on the object. An exception will be thrown if
44+
/// you try to use the device in a way that requires it to be present.
2845
/// </summary>
29-
public IDevice? BaseDevice { get; set; }
46+
/// <remarks>
47+
/// This property provides access to the specific <c>TDevice</c> instance associated with the current event.
48+
/// </remarks>
49+
/// <value>
50+
/// An instance of <c>TDevice</c> that triggered this event. This value is set when
51+
/// the event args are created and remains constant for the lifetime of the event
52+
/// args instance.
53+
/// </value>
54+
TDevice Device { get; }
55+
}
56+
57+
/// <summary>
58+
/// Event arguments given whenever a device is added or removed from the system, providing strongly-typed access to the device that triggered the event.
59+
/// </summary>
60+
/// <typeparam name="TDevice">The type of device associated with this event, which must implement <see cref="IDevice"/>.</typeparam>
61+
public abstract class DeviceEventArgs<TDevice> : EventArgs, IDeviceEventArgs<TDevice>
62+
where TDevice : IDevice
63+
{
64+
/// <inheritdoc />
65+
public TDevice Device { get; }
3066

3167
/// <summary>
32-
/// Constructs a new instance of the <see cref="DeviceEventArgs"/> class.
68+
/// Constructs a new instance of the <see cref="DeviceEventArgs{TDevice}"/> class.
3369
/// </summary>
34-
/// <param name="device">
35-
/// The device that is originating this event.
36-
/// </param>
37-
public DeviceEventArgs(IDevice? device)
70+
protected DeviceEventArgs(TDevice device)
3871
{
39-
BaseDevice = device;
72+
Device = device;
4073
}
4174
}
4275
}

Yubico.Core/src/Yubico/Core/Devices/Hid/HidDeviceEventArgs.cs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,17 @@ namespace Yubico.Core.Devices.Hid
1717
/// <summary>
1818
/// Event arguments given whenever a HID device is added or removed from the system.
1919
/// </summary>
20-
public class HidDeviceEventArgs : DeviceEventArgs
20+
public class HidDeviceEventArgs : DeviceEventArgs<IHidDevice>
2121
{
22-
/// <summary>
23-
/// The HID device that originated the event.
24-
/// </summary>
25-
/// <remarks>
26-
/// This property will always be populated, regardless of whether this is an arrival event or a removal event.
27-
/// If the device was removed, not all members will be available on the object. An exception will be thrown if
28-
/// you try to use the device in a way that requires it to be present.
29-
/// </remarks>
30-
public IHidDevice? Device { get; set; }
3122

3223
/// <summary>
3324
/// Constructs a new instance of the <see cref="HidDeviceEventArgs"/> class.
3425
/// </summary>
3526
/// <param name="device">
3627
/// The HID device that is originating this event.
3728
/// </param>
38-
public HidDeviceEventArgs(IHidDevice? device) : base(device)
29+
public HidDeviceEventArgs(IHidDevice device) : base(device)
3930
{
40-
Device = device;
4131
}
4232
}
4333
}

Yubico.Core/src/Yubico/Core/Devices/SmartCard/SmartCardDeviceEventArgs.cs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,8 @@ namespace Yubico.Core.Devices.SmartCard
1717
/// <summary>
1818
/// Event arguments given whenever a smart card device is added or removed from the system.
1919
/// </summary>
20-
public class SmartCardDeviceEventArgs : DeviceEventArgs
20+
public class SmartCardDeviceEventArgs : DeviceEventArgs<ISmartCardDevice>
2121
{
22-
/// <summary>
23-
/// The smart card device that originated the event.
24-
/// </summary>
25-
/// <remarks>
26-
/// This property will always be populated, regardless of whether this is an arrival event or a removal event.
27-
/// If the device was removed, not all members will be available on the object. An exception will be thrown if
28-
/// you try to use the device in a way that requires it to be present.
29-
/// </remarks>
30-
public ISmartCardDevice Device { get; set; }
31-
3222
/// <summary>
3323
/// Constructs a new instance of the <see cref="SmartCardDeviceEventArgs"/> class.
3424
/// </summary>
@@ -37,7 +27,6 @@ public class SmartCardDeviceEventArgs : DeviceEventArgs
3727
/// </param>
3828
public SmartCardDeviceEventArgs(ISmartCardDevice device) : base(device)
3929
{
40-
Device = device;
4130
}
4231
}
4332
}

Yubico.YubiKey/src/Yubico/YubiKey/YubiKeyDeviceListener.cs

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,7 @@ public class YubiKeyDeviceListener : IDisposable
4646
/// An instance of a <see cref="YubiKeyDeviceListener"/>.
4747
/// </summary>
4848
public static YubiKeyDeviceListener Instance => _lazyInstance ??= new YubiKeyDeviceListener();
49-
50-
internal static bool IsListenerRunning => !(_lazyInstance is null);
51-
49+
5250
/// <summary>
5351
/// Disposes and closes the singleton instance of <see cref="YubiKeyDeviceListener"/>.
5452
/// </summary>
@@ -74,12 +72,17 @@ public class YubiKeyDeviceListener : IDisposable
7472
/// </remarks>
7573
public static void StopListening()
7674
{
77-
if (_lazyInstance != null)
75+
if (_lazyInstance == null)
7876
{
79-
_lazyInstance.Dispose();
80-
_lazyInstance = null;
77+
return;
8178
}
79+
80+
_lazyInstance.Dispose();
81+
_lazyInstance = null;
8282
}
83+
84+
internal static bool IsListenerRunning => !(_lazyInstance is null);
85+
internal List<IYubiKeyDevice> GetAll() => _internalCache.Keys.ToList();
8386

8487
private static YubiKeyDeviceListener? _lazyInstance;
8588

@@ -94,7 +97,8 @@ public static void StopListening()
9497
private readonly Task _listenTask;
9598
private readonly CancellationTokenSource _tokenSource = new CancellationTokenSource();
9699
private CancellationToken CancellationToken => _tokenSource.Token;
97-
100+
101+
private bool _isDisposed;
98102
private bool _isListening;
99103

100104
private YubiKeyDeviceListener()
@@ -109,22 +113,14 @@ private YubiKeyDeviceListener()
109113
_listenTask = ListenForChanges();
110114
}
111115

112-
internal List<IYubiKeyDevice> GetAll() => _internalCache.Keys.ToList();
113116

114-
private void ArriveHandler(object? sender, DeviceEventArgs e) => ListenerHandler("Arrival", e);
117+
private void ArriveHandler(object? _, IDeviceEventArgs<IDevice> e) => ListenerHandler("Arrival", e);
115118

116-
private void RemoveHandler(object? sender, DeviceEventArgs e) => ListenerHandler("Removal", e);
119+
private void RemoveHandler(object? _, IDeviceEventArgs<IDevice> e) => ListenerHandler("Removal", e);
117120

118-
private void ListenerHandler(string eventType, DeviceEventArgs e)
121+
private void ListenerHandler(string eventType, IDeviceEventArgs<IDevice> e)
119122
{
120-
IDevice? device = e.BaseDevice;
121-
string deviceType = e is HidDeviceEventArgs ? "HID" : "smart card";
122-
123-
_log.LogInformation(
124-
"{EventType} of {DeviceType} {Device} is triggering update.",
125-
eventType,
126-
deviceType,
127-
device);
123+
LogEvent(eventType, e);
128124
_ = _semaphore.Release();
129125
}
130126

@@ -344,6 +340,23 @@ private void CreateAndMarkNewYubiKey(YubiKeyDevice.YubicoDeviceWithInfo deviceWi
344340
/// Raises event on device removal.
345341
/// </summary>
346342
private void OnDeviceRemoved(YubiKeyDeviceEventArgs e) => Removed?.Invoke(typeof(YubiKeyDevice), e);
343+
344+
private void LogEvent(string eventType, IDeviceEventArgs<IDevice> e)
345+
{
346+
var device = e.Device;
347+
string deviceTypeText = device switch
348+
{
349+
ISmartCardDevice _ => "SMART CARD",
350+
IHidDevice _ => "HID",
351+
_ => "UNKNOWN"
352+
};
353+
354+
_log.LogInformation(
355+
"{EventType} of {DeviceType} {Device} is triggering update.",
356+
eventType,
357+
deviceTypeText,
358+
device);
359+
}
347360

348361
private static IEnumerable<IDevice> GetHidFidoDevices()
349362
{
@@ -384,13 +397,10 @@ private static IEnumerable<IDevice> GetSmartCardDevices()
384397
return Enumerable.Empty<IDevice>();
385398
}
386399

387-
private static void ErrorHandler(Exception exception) =>
388-
Log
400+
private static void ErrorHandler(Exception exception) => Log
389401
.GetLogger(typeof(YubiKeyDeviceListener).FullName!)
390402
.LogWarning($"Exception caught: {exception}");
391-
392-
private bool _isDisposed;
393-
403+
394404
/// <summary>
395405
/// Disposes the objects.
396406
/// </summary>

0 commit comments

Comments
 (0)