docs: backfill XML documentation across 756 files
v2-ci / build (push) Failing after 1m43s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped

Adds <summary>, <param>, <typeparam>, and <inheritdoc/> tags to public
members surfaced by commentchecker — resolves 5,847 of 5,869 issues
(99.6%) across three /fixdocs passes.
This commit is contained in:
Joseph Doherty
2026-05-28 08:10:17 -04:00
parent f9fc7dd2e1
commit 64e3fbe035
756 changed files with 9876 additions and 96 deletions
@@ -44,6 +44,9 @@ public sealed record AlarmConditionState(
ImmutableList<AlarmComment> Comments)
{
/// <summary>Initial-load state for a newly registered alarm — everything in the "no-event" position.</summary>
/// <param name="alarmId">The unique identifier for the alarm.</param>
/// <param name="nowUtc">The current UTC timestamp.</param>
/// <returns>A fresh AlarmConditionState with all fields initialized to default/inactive values.</returns>
public static AlarmConditionState Fresh(string alarmId, DateTime nowUtc) => new(
AlarmId: alarmId,
Enabled: AlarmEnabledState.Enabled,
@@ -20,6 +20,10 @@ public sealed class AlarmPredicateContext : ScriptContext
private readonly IReadOnlyDictionary<string, DataValueSnapshot> _readCache;
private readonly Func<DateTime> _clock;
/// <summary>Initializes a new instance of the <see cref="AlarmPredicateContext"/> class.</summary>
/// <param name="readCache">The cached read values from tags.</param>
/// <param name="logger">The logger for diagnostics.</param>
/// <param name="clock">Optional custom clock for testing.</param>
public AlarmPredicateContext(
IReadOnlyDictionary<string, DataValueSnapshot> readCache,
ILogger logger,
@@ -30,6 +34,9 @@ public sealed class AlarmPredicateContext : ScriptContext
_clock = clock ?? (() => DateTime.UtcNow);
}
/// <summary>Gets a tag value from the read cache.</summary>
/// <param name="path">The tag path to retrieve.</param>
/// <inheritdoc />
public override DataValueSnapshot GetTag(string path)
{
if (string.IsNullOrWhiteSpace(path))
@@ -39,6 +46,10 @@ public sealed class AlarmPredicateContext : ScriptContext
: new DataValueSnapshot(null, 0x80340000u, null, _clock());
}
/// <summary>Rejects virtual tag writes for pure predicate semantics.</summary>
/// <param name="path">The virtual tag path.</param>
/// <param name="value">The value to write.</param>
/// <inheritdoc />
public override void SetVirtualTag(string path, object? value)
{
// Predicates must be pure — writing from an alarm script couples alarm state to
@@ -49,7 +60,9 @@ public sealed class AlarmPredicateContext : ScriptContext
"into a virtual tag whose value the alarm predicate then reads.");
}
/// <inheritdoc />
public override DateTime Now => _clock();
/// <inheritdoc />
public override ILogger Logger { get; }
}
@@ -15,9 +15,27 @@ namespace ZB.MOM.WW.OtOpcUa.Core.ScriptedAlarms;
/// </remarks>
public interface IAlarmStateStore
{
/// <summary>Loads the alarm state for a specific alarm identifier.</summary>
/// <param name="alarmId">The alarm identifier.</param>
/// <param name="ct">Cancellation token.</param>
/// <returns>The alarm state if found; otherwise null.</returns>
Task<AlarmConditionState?> LoadAsync(string alarmId, CancellationToken ct);
/// <summary>Loads all alarm states from the store.</summary>
/// <param name="ct">Cancellation token.</param>
/// <returns>A collection of all alarm states.</returns>
Task<IReadOnlyList<AlarmConditionState>> LoadAllAsync(CancellationToken ct);
/// <summary>Saves an alarm state to the store.</summary>
/// <param name="state">The alarm state to save.</param>
/// <param name="ct">Cancellation token.</param>
/// <returns>A task representing the save operation.</returns>
Task SaveAsync(AlarmConditionState state, CancellationToken ct);
/// <summary>Removes an alarm state from the store.</summary>
/// <param name="alarmId">The alarm identifier to remove.</param>
/// <param name="ct">Cancellation token.</param>
/// <returns>A task representing the remove operation.</returns>
Task RemoveAsync(string alarmId, CancellationToken ct);
}
@@ -27,18 +45,22 @@ public sealed class InMemoryAlarmStateStore : IAlarmStateStore
private readonly ConcurrentDictionary<string, AlarmConditionState> _map
= new(StringComparer.Ordinal);
/// <inheritdoc />
public Task<AlarmConditionState?> LoadAsync(string alarmId, CancellationToken ct)
=> Task.FromResult(_map.TryGetValue(alarmId, out var v) ? v : null);
/// <inheritdoc />
public Task<IReadOnlyList<AlarmConditionState>> LoadAllAsync(CancellationToken ct)
=> Task.FromResult<IReadOnlyList<AlarmConditionState>>(_map.Values.ToArray());
/// <inheritdoc />
public Task SaveAsync(AlarmConditionState state, CancellationToken ct)
{
_map[state.AlarmId] = state;
return Task.CompletedTask;
}
/// <inheritdoc />
public Task RemoveAsync(string alarmId, CancellationToken ct)
{
_map.TryRemove(alarmId, out _);
@@ -43,6 +43,9 @@ public static class MessageTemplate
/// "Input-quality policy" section in <c>docs/ScriptedAlarms.md</c>.
/// (Core.ScriptedAlarms-010)
/// </remarks>
/// <param name="template">The template string with {path} tokens.</param>
/// <param name="resolveTag">A function to resolve tag values by path.</param>
/// <returns>The resolved template string with tokens replaced or marked as unresolvable.</returns>
public static string Resolve(string template, Func<string, DataValueSnapshot?> resolveTag)
{
if (string.IsNullOrEmpty(template)) return template ?? string.Empty;
@@ -60,6 +63,8 @@ public static class MessageTemplate
}
/// <summary>Enumerate the token paths the template references. Used at publish time to validate references exist.</summary>
/// <param name="template">The template string to extract tokens from.</param>
/// <returns>A list of all token paths found in the template.</returns>
public static IReadOnlyList<string> ExtractTokenPaths(string? template)
{
if (string.IsNullOrEmpty(template)) return Array.Empty<string>();
@@ -32,6 +32,10 @@ public static class Part9StateMachine
/// branch-stack increment when a new active arrives while prior active is
/// still un-acked, and shelving suppression.
/// </summary>
/// <param name="current">The current alarm condition state.</param>
/// <param name="predicateTrue">Whether the predicate is true.</param>
/// <param name="nowUtc">The current UTC time.</param>
/// <returns>The transition result.</returns>
public static TransitionResult ApplyPredicate(
AlarmConditionState current,
bool predicateTrue,
@@ -86,6 +90,11 @@ public static class Part9StateMachine
}
/// <summary>Operator acknowledges the currently-active transition.</summary>
/// <param name="current">The current alarm condition state.</param>
/// <param name="user">The user who is acknowledging.</param>
/// <param name="comment">An optional comment.</param>
/// <param name="nowUtc">The current UTC time.</param>
/// <returns>The transition result.</returns>
public static TransitionResult ApplyAcknowledge(
AlarmConditionState current,
string user,
@@ -112,6 +121,11 @@ public static class Part9StateMachine
}
/// <summary>Operator confirms the cleared transition. Part 9 requires confirm after clear for retain-flag alarms.</summary>
/// <param name="current">The current alarm condition state.</param>
/// <param name="user">The user who is confirming.</param>
/// <param name="comment">An optional comment.</param>
/// <param name="nowUtc">The current UTC time.</param>
/// <returns>The transition result.</returns>
public static TransitionResult ApplyConfirm(
AlarmConditionState current,
string user,
@@ -137,6 +151,13 @@ public static class Part9StateMachine
return new TransitionResult(next, EmissionKind.Confirmed);
}
/// <summary>
/// Applies a one-shot shelving action.
/// </summary>
/// <param name="current">The current alarm condition state.</param>
/// <param name="user">The user applying the shelving.</param>
/// <param name="nowUtc">The current UTC time.</param>
/// <returns>The transition result.</returns>
public static TransitionResult ApplyOneShotShelve(
AlarmConditionState current, string user, DateTime nowUtc)
{
@@ -154,6 +175,14 @@ public static class Part9StateMachine
return new TransitionResult(next, EmissionKind.Shelved);
}
/// <summary>
/// Applies a timed shelving action.
/// </summary>
/// <param name="current">The current alarm condition state.</param>
/// <param name="user">The user applying the shelving.</param>
/// <param name="unshelveAtUtc">The UTC time at which the alarm should be unshelved.</param>
/// <param name="nowUtc">The current UTC time.</param>
/// <returns>The transition result.</returns>
public static TransitionResult ApplyTimedShelve(
AlarmConditionState current, string user, DateTime unshelveAtUtc, DateTime nowUtc)
{
@@ -172,6 +201,13 @@ public static class Part9StateMachine
return new TransitionResult(next, EmissionKind.Shelved);
}
/// <summary>
/// Applies an unshelving action.
/// </summary>
/// <param name="current">The current alarm condition state.</param>
/// <param name="user">The user applying the unshelving.</param>
/// <param name="nowUtc">The current UTC time.</param>
/// <returns>The transition result.</returns>
public static TransitionResult ApplyUnshelve(AlarmConditionState current, string user, DateTime nowUtc)
{
if (string.IsNullOrWhiteSpace(user)) throw new ArgumentException("User required.", nameof(user));
@@ -188,6 +224,13 @@ public static class Part9StateMachine
return new TransitionResult(next, EmissionKind.Unshelved);
}
/// <summary>
/// Applies an enable action.
/// </summary>
/// <param name="current">The current alarm condition state.</param>
/// <param name="user">The user enabling the alarm.</param>
/// <param name="nowUtc">The current UTC time.</param>
/// <returns>The transition result.</returns>
public static TransitionResult ApplyEnable(AlarmConditionState current, string user, DateTime nowUtc)
{
if (string.IsNullOrWhiteSpace(user)) throw new ArgumentException("User required.", nameof(user));
@@ -204,6 +247,13 @@ public static class Part9StateMachine
return new TransitionResult(next, EmissionKind.Enabled);
}
/// <summary>
/// Applies a disable action.
/// </summary>
/// <param name="current">The current alarm condition state.</param>
/// <param name="user">The user disabling the alarm.</param>
/// <param name="nowUtc">The current UTC time.</param>
/// <returns>The transition result.</returns>
public static TransitionResult ApplyDisable(AlarmConditionState current, string user, DateTime nowUtc)
{
if (string.IsNullOrWhiteSpace(user)) throw new ArgumentException("User required.", nameof(user));
@@ -220,6 +270,14 @@ public static class Part9StateMachine
return new TransitionResult(next, EmissionKind.Disabled);
}
/// <summary>
/// Applies an add comment action.
/// </summary>
/// <param name="current">The current alarm condition state.</param>
/// <param name="user">The user adding the comment.</param>
/// <param name="text">The comment text.</param>
/// <param name="nowUtc">The current UTC time.</param>
/// <returns>The transition result.</returns>
public static TransitionResult ApplyAddComment(
AlarmConditionState current, string user, string text, DateTime nowUtc)
{
@@ -236,6 +294,9 @@ public static class Part9StateMachine
/// the (possibly unshelved) state + emission hint so the engine knows to
/// publish an Unshelved event at the right moment.
/// </summary>
/// <param name="current">The current alarm condition state.</param>
/// <param name="nowUtc">The current UTC time.</param>
/// <returns>The transition result.</returns>
public static TransitionResult ApplyShelvingCheck(AlarmConditionState current, DateTime nowUtc)
{
if (current.Shelving.Kind != ShelvingKind.Timed) return TransitionResult.None(current);
@@ -284,7 +345,19 @@ public static class Part9StateMachine
/// </remarks>
public sealed record TransitionResult(AlarmConditionState State, EmissionKind Emission, string? NoOpReason = null)
{
/// <summary>
/// Creates a transition result with no change and no emission.
/// </summary>
/// <param name="state">The alarm condition state.</param>
/// <returns>The transition result.</returns>
public static TransitionResult None(AlarmConditionState state) => new(state, EmissionKind.None);
/// <summary>
/// Creates a transition result indicating a no-op operation with a reason.
/// </summary>
/// <param name="state">The alarm condition state.</param>
/// <param name="reason">The reason for the no-op.</param>
/// <returns>The transition result.</returns>
public static TransitionResult NoOp(AlarmConditionState state, string reason)
=> new(state, EmissionKind.None, reason);
}
@@ -96,6 +96,7 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// deterministic upstream push. Anything more involved should snapshot a
/// copy under the gate. (Core.ScriptedAlarms-013.)
/// </remarks>
/// <param name="alarmId">The alarm identifier to look up.</param>
internal IReadOnlyDictionary<string, DataValueSnapshot>? TryGetScratchReadCacheForTest(string alarmId)
=> _scratchByAlarmId.TryGetValue(alarmId, out var s) ? s.ReadCache : null;
@@ -111,6 +112,7 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// for reference-identity assertions on a quiesced engine.
/// (Core.ScriptedAlarms-013.)
/// </remarks>
/// <param name="alarmId">The alarm identifier to look up.</param>
internal AlarmPredicateContext? TryGetScratchContextForTest(string alarmId)
=> _scratchByAlarmId.TryGetValue(alarmId, out var s) ? s.Context : null;
private readonly ConcurrentDictionary<string, DataValueSnapshot> _valueCache
@@ -133,6 +135,15 @@ public sealed class ScriptedAlarmEngine : IDisposable
private readonly HashSet<Task> _inFlight = [];
private readonly object _inFlightLock = new();
/// <summary>
/// Initializes a new ScriptedAlarmEngine with the provided dependencies.
/// </summary>
/// <param name="upstream">The upstream tag source for reading tag values.</param>
/// <param name="store">The alarm state store for persistence.</param>
/// <param name="loggerFactory">The factory for creating alarm loggers.</param>
/// <param name="engineLogger">The logger for engine-level diagnostics.</param>
/// <param name="clock">Optional function providing the current UTC time; defaults to DateTime.UtcNow.</param>
/// <param name="scriptTimeout">Optional timeout for script execution; defaults to the evaluator's default timeout.</param>
public ScriptedAlarmEngine(
ITagUpstreamSource upstream,
IAlarmStateStore store,
@@ -152,6 +163,7 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// <summary>Raised for every emission the Part9StateMachine produces that the engine should publish.</summary>
public event EventHandler<ScriptedAlarmEvent>? OnEvent;
/// <summary>Gets the collection of loaded alarm identifiers.</summary>
public IReadOnlyCollection<string> LoadedAlarmIds => _alarms.Keys.ToArray();
/// <summary>
@@ -161,6 +173,8 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// the store (falling back to Fresh for first-load alarms), and recomputes
/// ActiveState per Phase 7 plan decision #14 (startup recovery).
/// </summary>
/// <param name="definitions">The alarm definitions to load.</param>
/// <param name="ct">The cancellation token.</param>
public async Task LoadAsync(IReadOnlyList<ScriptedAlarmDefinition> definitions, CancellationToken ct)
{
if (_disposed) throw new ObjectDisposedException(nameof(ScriptedAlarmEngine));
@@ -291,33 +305,71 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// Current persisted state for <paramref name="alarmId"/>. Returns null for
/// unknown alarm. Mainly used for diagnostics + the Admin UI status page.
/// </summary>
/// <param name="alarmId">The alarm identifier.</param>
public AlarmConditionState? GetState(string alarmId)
=> _alarms.TryGetValue(alarmId, out var s) ? s.Condition : null;
/// <summary>Gets the current persisted state for all loaded alarms.</summary>
public IReadOnlyCollection<AlarmConditionState> GetAllStates()
=> _alarms.Values.Select(a => a.Condition).ToArray();
/// <summary>Acknowledges the specified alarm on behalf of the given user.</summary>
/// <param name="alarmId">The alarm identifier.</param>
/// <param name="user">The user performing the acknowledgment.</param>
/// <param name="comment">An optional comment to attach to the acknowledgment.</param>
/// <param name="ct">The cancellation token.</param>
public Task AcknowledgeAsync(string alarmId, string user, string? comment, CancellationToken ct)
=> ApplyAsync(alarmId, ct, cur => Part9StateMachine.ApplyAcknowledge(cur, user, comment, _clock()));
/// <summary>Confirms the specified alarm on behalf of the given user.</summary>
/// <param name="alarmId">The alarm identifier.</param>
/// <param name="user">The user performing the confirmation.</param>
/// <param name="comment">An optional comment to attach to the confirmation.</param>
/// <param name="ct">The cancellation token.</param>
public Task ConfirmAsync(string alarmId, string user, string? comment, CancellationToken ct)
=> ApplyAsync(alarmId, ct, cur => Part9StateMachine.ApplyConfirm(cur, user, comment, _clock()));
/// <summary>Applies a one-shot shelve to the specified alarm on behalf of the given user.</summary>
/// <param name="alarmId">The alarm identifier.</param>
/// <param name="user">The user performing the shelve operation.</param>
/// <param name="ct">The cancellation token.</param>
public Task OneShotShelveAsync(string alarmId, string user, CancellationToken ct)
=> ApplyAsync(alarmId, ct, cur => Part9StateMachine.ApplyOneShotShelve(cur, user, _clock()));
/// <summary>Applies a timed shelve to the specified alarm on behalf of the given user.</summary>
/// <param name="alarmId">The alarm identifier.</param>
/// <param name="user">The user performing the shelve operation.</param>
/// <param name="unshelveAtUtc">The UTC time at which the shelve will automatically expire.</param>
/// <param name="ct">The cancellation token.</param>
public Task TimedShelveAsync(string alarmId, string user, DateTime unshelveAtUtc, CancellationToken ct)
=> ApplyAsync(alarmId, ct, cur => Part9StateMachine.ApplyTimedShelve(cur, user, unshelveAtUtc, _clock()));
/// <summary>Removes any shelve from the specified alarm on behalf of the given user.</summary>
/// <param name="alarmId">The alarm identifier.</param>
/// <param name="user">The user performing the unshelve operation.</param>
/// <param name="ct">The cancellation token.</param>
public Task UnshelveAsync(string alarmId, string user, CancellationToken ct)
=> ApplyAsync(alarmId, ct, cur => Part9StateMachine.ApplyUnshelve(cur, user, _clock()));
/// <summary>Enables the specified alarm on behalf of the given user.</summary>
/// <param name="alarmId">The alarm identifier.</param>
/// <param name="user">The user performing the enable operation.</param>
/// <param name="ct">The cancellation token.</param>
public Task EnableAsync(string alarmId, string user, CancellationToken ct)
=> ApplyAsync(alarmId, ct, cur => Part9StateMachine.ApplyEnable(cur, user, _clock()));
/// <summary>Disables the specified alarm on behalf of the given user.</summary>
/// <param name="alarmId">The alarm identifier.</param>
/// <param name="user">The user performing the disable operation.</param>
/// <param name="ct">The cancellation token.</param>
public Task DisableAsync(string alarmId, string user, CancellationToken ct)
=> ApplyAsync(alarmId, ct, cur => Part9StateMachine.ApplyDisable(cur, user, _clock()));
/// <summary>Adds a comment to the specified alarm on behalf of the given user.</summary>
/// <param name="alarmId">The alarm identifier.</param>
/// <param name="user">The user adding the comment.</param>
/// <param name="text">The comment text.</param>
/// <param name="ct">The cancellation token.</param>
public Task AddCommentAsync(string alarmId, string user, string text, CancellationToken ct)
=> ApplyAsync(alarmId, ct, cur => Part9StateMachine.ApplyAddComment(cur, user, text, _clock()));
@@ -369,6 +421,8 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// so driver-side dispatch isn't blocked; the background task is tracked so
/// <see cref="Dispose"/> can drain it. (Core.ScriptedAlarms-006)
/// </summary>
/// <param name="path">The upstream tag path that changed.</param>
/// <param name="value">The new data value snapshot.</param>
internal void OnUpstreamChange(string path, DataValueSnapshot value)
{
_valueCache[path] = value;
@@ -658,6 +712,7 @@ public sealed class ScriptedAlarmEngine : IDisposable
"ScriptedAlarmEngine not loaded. Call LoadAsync first.");
}
/// <summary>Disposes the engine, cleaning up resources and waiting for in-flight background tasks.</summary>
public void Dispose()
{
if (_disposed) return;
@@ -729,9 +784,17 @@ public sealed class ScriptedAlarmEngine : IDisposable
/// </remarks>
private sealed class AlarmScratch
{
/// <summary>Gets the read cache dictionary containing current upstream tag values.</summary>
public Dictionary<string, DataValueSnapshot> ReadCache { get; }
/// <summary>Gets the predicate evaluation context.</summary>
public AlarmPredicateContext Context { get; }
/// <summary>
/// Initializes a new AlarmScratch with the specified inputs, logger, and clock.
/// </summary>
/// <param name="inputs">The set of input tag paths this alarm references.</param>
/// <param name="logger">The logger for this alarm's diagnostics.</param>
/// <param name="clock">Function providing the current UTC time.</param>
public AlarmScratch(IReadOnlySet<string> inputs, ILogger logger, Func<DateTime> clock)
{
// Pre-size to the expected input count so the first refill doesn't pay the
@@ -768,6 +831,14 @@ public sealed record ScriptedAlarmEvent(
/// </summary>
public interface ITagUpstreamSource
{
/// <summary>Reads a tag value synchronously.</summary>
/// <param name="path">The tag path to read.</param>
/// <returns>A data value snapshot containing the tag value and status.</returns>
DataValueSnapshot ReadTag(string path);
/// <summary>Subscribes to upstream tag changes.</summary>
/// <param name="path">The tag path to observe.</param>
/// <param name="observer">Callback invoked when the tag value changes.</param>
/// <returns>A subscription handle that removes the observer when disposed.</returns>
IDisposable SubscribeTag(string path, Action<string, DataValueSnapshot> observer);
}
@@ -31,14 +31,18 @@ public sealed class ScriptedAlarmSource : IAlarmSource, IDisposable
= new(StringComparer.Ordinal);
private bool _disposed;
/// <summary>Initializes a new instance of the <see cref="ScriptedAlarmSource"/> class.</summary>
/// <param name="engine">The scripted alarm engine to expose.</param>
public ScriptedAlarmSource(ScriptedAlarmEngine engine)
{
_engine = engine ?? throw new ArgumentNullException(nameof(engine));
_engine.OnEvent += OnEngineEvent;
}
/// <summary>Occurs when an alarm event is raised by the engine.</summary>
public event EventHandler<AlarmEventArgs>? OnAlarmEvent;
/// <inheritdoc />
public Task<IAlarmSubscriptionHandle> SubscribeAlarmsAsync(
IReadOnlyList<string> sourceNodeIds, CancellationToken cancellationToken)
{
@@ -49,6 +53,7 @@ public sealed class ScriptedAlarmSource : IAlarmSource, IDisposable
return Task.FromResult<IAlarmSubscriptionHandle>(handle);
}
/// <inheritdoc />
public Task UnsubscribeAlarmsAsync(IAlarmSubscriptionHandle handle, CancellationToken cancellationToken)
{
if (handle is null) throw new ArgumentNullException(nameof(handle));
@@ -56,6 +61,7 @@ public sealed class ScriptedAlarmSource : IAlarmSource, IDisposable
return Task.CompletedTask;
}
/// <inheritdoc />
public async Task AcknowledgeAsync(
IReadOnlyList<AlarmAcknowledgeRequest> acknowledgements, CancellationToken cancellationToken)
{
@@ -104,6 +110,7 @@ public sealed class ScriptedAlarmSource : IAlarmSource, IDisposable
return false;
}
/// <summary>Releases resources used by the <see cref="ScriptedAlarmSource"/>.</summary>
public void Dispose()
{
if (_disposed) return;
@@ -114,7 +121,10 @@ public sealed class ScriptedAlarmSource : IAlarmSource, IDisposable
private sealed class SubscriptionHandle : IAlarmSubscriptionHandle
{
/// <summary>Initializes a new instance of the <see cref="SubscriptionHandle"/> class.</summary>
/// <param name="id">The diagnostic ID for this subscription handle.</param>
public SubscriptionHandle(string id) { DiagnosticId = id; }
/// <summary>Gets the diagnostic ID that uniquely identifies this subscription.</summary>
public string DiagnosticId { get; }
}