review(Driver.OpcUaClient.Contracts): first review; fix TryResolve nullability + [Range] guards

First review at 7286d320. -001 (Medium): TryResolve session param -> ISession? matching the
null guard + out-contract doc. -003: [Range] on MaxDiscoveredNodes/MaxBrowseDepth, drop dead
[Display]. -002 (NamespaceMap pulls full SDK into a DTO project) Open. Surfaced cross-module:
the OpcUaClient.Browser serializer lacks JsonStringEnumConverter (enum-as-int bug).
This commit is contained in:
Joseph Doherty
2026-06-19 12:22:53 -04:00
parent a7ce742763
commit 9244e506c9
3 changed files with 90 additions and 5 deletions
@@ -110,12 +110,16 @@ public sealed class NamespaceMap
/// <see cref="ToStableReference"/> or a plain <c>ns=N;…</c> NodeId — against the
/// <paramref name="currentSession"/>'s namespace table. A <c>nsu=…</c> reference is
/// re-bound through the current session's URI table so a remote reorder since connect
/// time is corrected. Returns false for empty/malformed input or an unknown URI.
/// time is corrected. Returns false for empty/malformed input, an unknown URI, or a
/// null session (defensive — callers on the reconnect path may pass a session that has
/// been torn down concurrently).
/// </summary>
/// <param name="currentSession">The OPC UA session whose namespace table to resolve against.</param>
/// <param name="currentSession">The live OPC UA session to resolve against. Passing null
/// returns false rather than throwing, matching the TryXxx contract.</param>
/// <param name="reference">The reference string to resolve (either <c>nsu=…</c> or <c>ns=N;…</c> format).</param>
/// <param name="nodeId">On success, the resolved NodeId; otherwise NodeId.Null.</param>
public static bool TryResolve(ISession currentSession, string reference, out NodeId nodeId)
/// <param name="nodeId">On success, the resolved NodeId; on failure, <c>NodeId.Null</c>.
/// Use <see cref="NodeId.IsNull(NodeId)"/> — not <c>== null</c> — to test this value.</param>
public static bool TryResolve(ISession? currentSession, string reference, out NodeId nodeId)
{
nodeId = NodeId.Null;
if (currentSession is null || string.IsNullOrWhiteSpace(reference)) return false;
@@ -128,6 +128,7 @@ public sealed class OpcUaClientDriverOptions
/// written to the driver health surface; the partially-discovered tree is still
/// projected into the local address space.
/// </summary>
[Range(1, int.MaxValue)]
public int MaxDiscoveredNodes { get; init; } = 10_000;
/// <summary>
@@ -135,6 +136,7 @@ public sealed class OpcUaClientDriverOptions
/// OPC UA information models, shallow enough that cyclic graphs can't spin the
/// browse forever.
/// </summary>
[Range(1, int.MaxValue)]
public int MaxBrowseDepth { get; init; } = 10;
/// <summary>
@@ -171,7 +173,6 @@ public sealed class OpcUaClientDriverOptions
/// Timeout for the AdminUI Test Connect probe, in seconds. The AdminUI clamps to a
/// 60s server-side maximum; this default is what the form pre-fills for new instances.
/// </summary>
[Display(Name = "Probe timeout (seconds)", Description = "Connection test timeout. Default 15s.", GroupName = "Diagnostics")]
[Range(1, 60)]
public int ProbeTimeoutSeconds { get; init; } = 15;
}