Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
dc71dd2
Enable #nullable on Opc.Ua.Bindings.Https (3 files)
marcschier May 1, 2026
bf523e4
Enable #nullable on Opc.Ua project (50 files)
marcschier May 1, 2026
22ff7d0
Enable #nullable on Opc.Ua.Types simple files (107 files)
marcschier May 1, 2026
6171646
Make IDecoder/IEncoder fieldName params nullable
marcschier May 1, 2026
ffb17ed
Enable #nullable on more Opc.Ua.Types files (10 more)
marcschier May 1, 2026
21ebd2a
Enable #nullable on more Opc.Ua.Types files (16 more, 133/187 total)
marcschier May 1, 2026
041b22b
Enable #nullable on Opc.Ua.Core simple files (49 more, 66/147 total)
marcschier May 1, 2026
a3a2c86
Make ClientBase properties non-null with null-forgiving assertion
marcschier May 1, 2026
14bbe53
Enable #nullable on BinaryEncoder
marcschier May 1, 2026
51c5c07
Enable #nullable on Opc.Ua.Types State files (initial batch)
marcschier May 1, 2026
8c59a40
Enable #nullable on more Opc.Ua.Types State files
marcschier May 1, 2026
27f9e5b
Enable #nullable on NodeStateCollection.cs
marcschier May 1, 2026
158017e
Enable #nullable on BinaryDecoder
marcschier May 1, 2026
77896a1
Enable #nullable on MethodState.cs; fix NodeStateCollection downstream
marcschier May 1, 2026
020d0bf
Enable #nullable on XmlEncoder
marcschier May 1, 2026
35a872c
Enable #nullable on Opc.Ua.Types Utils + BuiltIn small files
marcschier May 1, 2026
704fe13
Enable #nullable on TypeTable.cs
marcschier May 1, 2026
1ed577b
Enable #nullable on BaseVariableTypeState.cs
marcschier May 1, 2026
3fe8b21
Enable #nullable on Node.cs
marcschier May 1, 2026
2a46696
Enable #nullable on XmlDecoder
marcschier May 1, 2026
8d3ebc1
Enable #nullable on BuiltIn class types and helpers
marcschier May 1, 2026
146c4ff
Enable #nullable on NodeTable.cs
marcschier May 1, 2026
f2cada9
Enable #nullable on Node.cs (additional fixes) and ReferenceTable.cs
marcschier May 1, 2026
60c4a88
Enable #nullable on XmlParser
marcschier May 1, 2026
dfc1da2
Enable #nullable on NodeSet.cs
marcschier May 1, 2026
df14a89
Enable #nullable on Opc.Ua.Types Schema
marcschier May 1, 2026
fc0553a
Fix multi-target nullable issues for Node.cs, ReferenceTable.cs, Node…
marcschier May 1, 2026
a1c187e
Fix multi-target nullable issues in encoder/decoder files
marcschier May 1, 2026
cf3643e
Fix NodeSet.cs net472-specific nullable issue
marcschier May 1, 2026
cc255cf
Fix integration errors after parallel nullable migration
marcschier May 1, 2026
00fc763
Enable #nullable on Opc.Ua.Core Stack/Tcp (WIP)
marcschier May 1, 2026
5314eeb
Update TCP nullable annotations
marcschier May 1, 2026
23e716c
Fix more nullable in TCP
marcschier May 1, 2026
4c6308e
WIP: nullable enable on Core Client/Server
marcschier May 1, 2026
eabba1d
Fix TCP transport listener and client channel nullable
marcschier May 1, 2026
dc356ab
Enable #nullable on BaseVariableState
Copilot May 1, 2026
a397375
Apply nullable annotations to Core Client/Server
marcschier May 1, 2026
dfc8779
Enable #nullable on Opc.Ua.Core remaining stack files
marcschier May 1, 2026
31b803d
WIP: nullable annotations on NodeState
Copilot May 1, 2026
b4330c7
WIP: more nullable annotations on NodeState
Copilot May 1, 2026
c796581
Enable #nullable on Opc.Ua.Core Security/Certificates (partial)
marcschier May 1, 2026
400118b
WIP: more nullable progress on NodeState
Copilot May 1, 2026
1fd52fe
Fix nullable annotations in Core Client/Server files
marcschier May 1, 2026
eaa94e0
Make IChannelOutgoingRequest.OperationCompleted response nullable
marcschier May 1, 2026
b88fa07
Enable nullable on NodeState.cs (net10 clean)
Copilot May 1, 2026
5bb216d
Fix multi-target nullable issues in NodeState
Copilot May 1, 2026
e4ac22b
Enable #nullable on Opc.Ua.Core Security/Certificates
marcschier May 1, 2026
a7953a7
Enable #nullable on Opc.Ua.Core Configuration/Bindings/Schema
marcschier May 1, 2026
de34f85
Fix downstream consumers of NodeState nullable changes
Copilot May 1, 2026
431e65b
Fix Core Tcp/Channel integration errors after parallel migration
marcschier May 1, 2026
799f87a
Enable #nullable on remaining Opc.Ua.Core files
marcschier May 1, 2026
7b5353a
Enable #nullable on remaining ConfiguredEndpoints and CertificateVali…
marcschier May 2, 2026
c88eaf5
Switch from per-file #nullable enable directives to project-level Nul…
marcschier May 2, 2026
c52e45f
Fix CI test failures from over-aggressive nullable migration
marcschier May 2, 2026
60de955
Fix more Core test failures from over-aggressive nullable migration
marcschier May 2, 2026
c5a438d
Fix more session/identity/state regressions from nullable migration
marcschier May 2, 2026
10c4117
Enable nullable on Opc.Ua.Configuration; remove #nullable disable fro…
marcschier May 2, 2026
9d67751
Batch 4c: DataTypeDefinitionExtension + MonitoredItem displayName com…
May 2, 2026
d49788b
Batch 1: Small files - eliminate pragma + inline ! suppressions
May 2, 2026
c672fe8
Batch 2: Comments + DiagnosticInfo? param refactor
May 2, 2026
153c066
Batch 3: SessionObsolete, ReconnectHandler, DefaultSessionFactory com…
May 2, 2026
1832f89
Batch 4a: Subscription.cs comments
May 2, 2026
ac34514
Batch 4b: ComplexTypeSystem + MonitoredItem comments
May 2, 2026
e7f392b
Restore displayName! that batch 1 cherry-pick erased
May 2, 2026
b529c1a
Session.cs: drop ! after Debug.Assert (compiler narrows on assert)
May 2, 2026
8d04a80
Session.cs: class-level remarks + capture endpointUrl local
May 2, 2026
84398e1
Session.cs: add class-level remarks for ! suppressions
May 2, 2026
f8d9e5c
Session.cs: change securityPolicyUri/tokenSecurityPolicyUri to non-nu…
May 2, 2026
a07a83b
Session.cs: more inline ! reductions + comments
May 2, 2026
74e1fbf
Session.cs: document ValidateClientConfiguration as ! gate
May 2, 2026
6170d3d
Restore Session.cs class-level remarks (lost to parallel reset)
May 2, 2026
77b2c10
Session.cs: re-apply security policy URI non-nullable refactor
May 2, 2026
1b02e5d
Minimize null-forgiving (!) operators across Stack and Libraries proj…
May 2, 2026
cab0deb
Fix latent bugs flagged during nullable-reference cleanup audit
May 2, 2026
4adef78
Merge master into nullable4
May 2, 2026
5f31cff
Enable nullable on Opc.Ua.Gds.Client.Common and Opc.Ua.Gds.Common
May 3, 2026
4acabb7
Enable nullable on Opc.Ua.Security.Certificates
May 3, 2026
245e92b
Enable nullable on Opc.Ua.Server
May 3, 2026
01d72a5
Enable nullable on Opc.Ua.Gds.Server.Common; revert NodeId? on Gds.Cl…
May 3, 2026
1988bca
Server: minimize ! and fix logic inversions introduced by 245e92b1d
May 4, 2026
1581531
Server: fix 243 logic inversions introduced by 245e92b1d
May 4, 2026
9f3bf03
Enable nullable on Opc.Ua.Client.ComplexTypes
May 4, 2026
20504db
Enable nullable on Applications projects
May 4, 2026
3a7971b
! reduction Phase 1: ValidateRequest [NotNull] + StandardServer cleanup
May 4, 2026
a4d9487
! reduction Phase 3: fix 13 (expr as Type)! latent bugs
May 4, 2026
38def19
! reduction Phase 2': capture-once locals for chained ! property access
May 4, 2026
ff1e77d
Fix Quickstarts.Servers nullable build errors (CI blocking)
May 4, 2026
385ec29
Fix 10 latent null-deref / dead-code bugs flagged during nullable mig…
May 4, 2026
7e2f415
Fix CI nullable build errors in Opc.Ua.Server (CS8602/8604/8601/8600)
May 5, 2026
7d94bb1
Merge remote-tracking branch 'origin/master' into nullable4
May 5, 2026
8c17d51
Enable nullable in Libraries/Opc.Ua.Gds.Common
May 5, 2026
8c4bd7d
Enable nullable in Libraries/Opc.Ua.PubSub
May 5, 2026
7eb6ba8
Fix CI nullable build errors from master merge
May 5, 2026
7369bb3
Fix CS8764/CS8765 nullable override mismatches in Gds.Server.Common
May 5, 2026
cc8943d
Fix CS86xx errors in Quickstarts.Servers + widen MonitoredItem ctor
May 5, 2026
13ec9ef
Fix CS8604 in MonitoredItem.cs:153,227 - m_filterToUse to ReportCreat…
May 5, 2026
48a08dd
Tests/Opc.Ua.Client.Tests: enable nullable annotation context
May 5, 2026
1d9df71
Revert ServerSystemContext.OperationContext throw to nullable return
May 5, 2026
4a502c4
Fix CS8604 cascade after ServerSystemContext.OperationContext nullabl…
May 5, 2026
6196fb3
Fix CS1574 XML cref in ServerSystemContext.cs:92
May 5, 2026
e3e0314
Fix CS8602 SampleNodeManager.cs:1946 - systemContext.OperationContext…
May 5, 2026
deb49de
Fix inverted TryGetValue logic in LookupNodeInComponentCache
May 5, 2026
acda44f
Apply same TryGetValue inversion fix to AsyncCustomNodeManager.Lookup…
May 5, 2026
5f8fbed
Fix two more inversions surfaced by tests: ValidateRolePermissions + …
May 5, 2026
334d89d
Fix CodeQL/Release/net472 nullable build errors
May 5, 2026
e23ae49
Fix CS8602 MasterNodeManager.cs:1716 - context is also nullable
May 5, 2026
7c85851
Add null-forgiving operator audit report to plans/
May 5, 2026
0a390dc
Cleanup-4: required modifier on PubSub EventArgs/DTO properties
May 5, 2026
556a4eb
Cleanup-3: [MemberNotNull] attributes on lifecycle methods in Opc.Ua.…
May 5, 2026
d4f05ee
Cleanup-2: ArraySegment.GetArray helper, OfType refactor, 2 latent bu…
May 5, 2026
a6f05c9
Cleanup-5: GetElementType pattern + Nonce dispose nullable
May 5, 2026
11ee311
Cleanup-1: nullable fieldName on IEncoder/IDecoder + AuditEvent source
May 5, 2026
761fca5
Merge remote-tracking branch 'origin/master' into nullable4
May 5, 2026
061b584
Fix CS8625 in ConfiguredEndpoint test calls
May 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
67 changes: 44 additions & 23 deletions Applications/ConsoleReferenceClient/ClientSamples.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ public class ClientSamples

public ClientSamples(
ITelemetryContext telemetry,
Action<IList, IList> validateResponse,
ManualResetEvent quitEvent = null,
Action<IList, IList>? validateResponse,
ManualResetEvent? quitEvent = null,
bool verbose = false)
{
m_telemetry = telemetry;
Expand Down Expand Up @@ -587,9 +587,16 @@ public async Task<IList<INode>> FetchAllNodesNodeCacheAsync(
// add root node
if (addRootNode)
{
INode rootNode = await uaClient.Session.NodeCache.FindAsync(startingNode, ct)
INode? rootNode = await uaClient.Session.NodeCache.FindAsync(startingNode, ct)
.ConfigureAwait(false);
nodeDictionary[rootNode.NodeId] = rootNode;
if (rootNode == null)
{
m_logger.LogWarning("Root node {NodeId} not found, skipping", startingNode);
}
else
{
nodeDictionary[rootNode.NodeId] = rootNode;
}
}

int searchDepth = 0;
Expand Down Expand Up @@ -625,7 +632,7 @@ public async Task<IList<INode>> FetchAllNodesNodeCacheAsync(
// no need to browse property types
if (node is VariableNode variableNode)
{
IReference hasTypeDefinition = variableNode.ReferenceTable
IReference? hasTypeDefinition = variableNode.ReferenceTable
.FirstOrDefault(r =>
r.ReferenceTypeId
.Equals(ReferenceTypeIds.HasTypeDefinition));
Expand Down Expand Up @@ -712,7 +719,7 @@ public async Task<IList<INode>> FetchAllNodesNodeCacheAsync(
public async Task<ArrayOf<ReferenceDescription>> ManagedBrowseFullAddressSpaceAsync(
IUAClient uaClient,
NodeId startingNode = default,
BrowseDescription browseDescription = null,
BrowseDescription? browseDescription = null,
CancellationToken ct = default)
{
ContinuationPointPolicy policyBackup = uaClient.Session.ContinuationPointPolicy;
Expand Down Expand Up @@ -888,7 +895,7 @@ await uaClient
public async Task<ArrayOf<ReferenceDescription>> BrowseFullAddressSpaceAsync(
IUAClient uaClient,
NodeId startingNode = default,
BrowseDescription browseDescription = null,
BrowseDescription? browseDescription = null,
CancellationToken ct = default)
{
var stopWatch = new Stopwatch();
Expand Down Expand Up @@ -1176,8 +1183,8 @@ public async Task<ResultSet<DataValue>> ReadAllValuesAsync(
CancellationToken ct = default)
{
bool retrySingleRead = false;
List<DataValue> values = null;
List<ServiceResult> errors = null;
List<DataValue>? values = null;
List<ServiceResult>? errors = null;

do
{
Expand Down Expand Up @@ -1259,7 +1266,7 @@ public async Task<ResultSet<DataValue>> ReadAllValuesAsync(
}
} while (retrySingleRead);

return ResultSet.From(values, errors);
return ResultSet.From(values!, errors!);
}

/// <summary>
Expand Down Expand Up @@ -1361,7 +1368,7 @@ public static string FormatValueAsJson(
IServiceMessageContext messageContext,
string name,
DataValue value,
JsonEncoderOptions jsonEncodingType = null)
JsonEncoderOptions? jsonEncodingType = null)
{
string textbuffer;
using (var jsonEncoder = new JsonEncoder(messageContext, jsonEncodingType))
Expand Down Expand Up @@ -1436,7 +1443,13 @@ private void OnMonitoredItemNotification(
try
{
// Log MonitoredItem Notification event
var notification = e.NotificationValue as MonitoredItemNotification;
if (e.NotificationValue is not MonitoredItemNotification notification)
{
m_logger.LogWarning(
"Unexpected notification type: {Type}",
e.NotificationValue?.GetType().Name ?? "null");
return;
}
DateTime localTime = notification.Value.SourceTimestamp.ToLocalTime();
m_logger.LogInformation(
"Notification: {SequenceNumber} \"{NodeId}\" and Value = {Value} at [{CurrentTime}].",
Expand All @@ -1461,7 +1474,13 @@ private void OnMonitoredItemEventNotification(
try
{
// Log MonitoredItem Notification event
var notification = e.NotificationValue as EventFieldList;
if (e.NotificationValue is not EventFieldList notification)
{
m_logger.LogWarning(
"Unexpected event notification type: {Type}",
e.NotificationValue?.GetType().Name ?? "null");
return;
}

foreach (KeyValuePair<int, ArrayOf<QualifiedName>> entry in m_desiredEventFields)
{
Expand Down Expand Up @@ -1559,7 +1578,7 @@ private static ArrayOf<BrowseDescription> CreateBrowseDescriptionCollectionFromN
var browseDescriptionCollection = new List<BrowseDescription>();
foreach (NodeId nodeId in nodeIdCollection)
{
BrowseDescription browseDescription = CoreUtils.Clone(template);
BrowseDescription browseDescription = CoreUtils.Clone(template)!;
browseDescription.NodeId = nodeId;
browseDescriptionCollection.Add(browseDescription);
}
Expand Down Expand Up @@ -1621,7 +1640,7 @@ public async Task<IReadOnlyDictionary<string, string>> ExportNodesToNodeSet2PerN
ISession session,
IList<INode> nodes,
string outputDirectory,
IReadOnlyCollection<string> targetNamespaces = null,
IReadOnlyCollection<string>? targetNamespaces = null,
CancellationToken cancellationToken = default)
{
if (session == null)
Expand All @@ -1637,7 +1656,7 @@ public async Task<IReadOnlyDictionary<string, string>> ExportNodesToNodeSet2PerN
throw new ArgumentException("Value cannot be null or whitespace.", nameof(outputDirectory));
}

HashSet<string> targetSet = targetNamespaces is { Count: > 0 }
HashSet<string>? targetSet = targetNamespaces is { Count: > 0 }
? new HashSet<string>(targetNamespaces, StringComparer.OrdinalIgnoreCase)
: null;

Expand All @@ -1658,16 +1677,17 @@ public async Task<IReadOnlyDictionary<string, string>> ExportNodesToNodeSet2PerN
.GroupBy(node => node.NodeId.NamespaceIndex)
.Where(group =>
{
string namespaceUri = session.NamespaceUris.GetString(group.Key);
string? namespaceUri = session.NamespaceUris.GetString(group.Key);
if (string.IsNullOrEmpty(namespaceUri))
{
return false;
}

if (targetSet != null)
{
// Caller asked for a specific set of namespaces.
return targetSet.Contains(namespaceUri);
// Caller asked for a specific set of namespaces. namespaceUri is non-null
// after !IsNullOrEmpty (NotNullWhen attribute not available on net48).
return targetSet.Contains(namespaceUri!);
}

// Default: exclude only the OPC UA base namespace; include companion specs.
Expand All @@ -1684,7 +1704,8 @@ public async Task<IReadOnlyDictionary<string, string>> ExportNodesToNodeSet2PerN
{
cancellationToken.ThrowIfCancellationRequested();

string namespaceUri = session.NamespaceUris.GetString(kvp.Key);
// The Where clause above filtered out null/empty namespace URIs.
string namespaceUri = session.NamespaceUris.GetString(kvp.Key)!;

// Create a safe filename from the namespace URI

Expand Down Expand Up @@ -1786,18 +1807,18 @@ private void ValidateResponse<TRequest, TResponse>(
{
if (m_validate != null)
{
m_validate(requests.ToArray(), responses.ToArray());
m_validate(requests.ToArray()!, responses.ToArray()!);
}
else
{
ClientBase.ValidateResponse(responses, requests);
}
}

private readonly Action<IList, IList> m_validate;
private readonly Action<IList, IList>? m_validate;
private readonly ITelemetryContext m_telemetry;
private readonly ILogger m_logger;
private readonly ManualResetEvent m_quitEvent;
private readonly ManualResetEvent? m_quitEvent;
private readonly bool m_verbose;
private readonly Dictionary<int, ArrayOf<QualifiedName>> m_desiredEventFields;
private int m_processedEvents;
Expand Down
46 changes: 24 additions & 22 deletions Applications/ConsoleReferenceClient/ConnectTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public sealed class ConnectTester : IDisposable
{
public ConnectTester(
ITelemetryContext telemetry,
ManualResetEvent quitEvent = null)
ManualResetEvent? quitEvent = null)
{
m_quitEvent = quitEvent;
m_telemetry = telemetry;
Expand Down Expand Up @@ -100,7 +100,7 @@ public async Task RunAsync(CancellationToken ct)
.LoadApplicationConfigurationAsync(silent: false, ct: ct)
.ConfigureAwait(false);

m_configuration.CertificateValidator.CertificateValidation += CertificateValidation;
m_configuration.CertificateValidator!.CertificateValidation += CertificateValidation;

// check the application certificate.
bool haveAppCertificate = await application
Expand All @@ -123,16 +123,17 @@ public async Task RunAsync(CancellationToken ct)
var sessionFactory = new DefaultSessionFactory(m_telemetry);
var userNameidentity = new UserIdentity(kUserName, new UTF8Encoding(false).GetBytes(kPassword));

foreach (EndpointDescription ii in endpoints.ToArray())
foreach (EndpointDescription ii in endpoints.ToArray()!)
{
string userCertificateFile = GetUserCertificateFile(ii.SecurityPolicyUri);
string securityPolicyUri = ii.SecurityPolicyUri!;
string userCertificateFile = GetUserCertificateFile(securityPolicyUri);

X509Certificate2 x509 = X509CertificateLoader.LoadPkcs12FromFile(
Path.Combine("..\\..\\pki\\trustedUser\\private",
userCertificateFile),
"password");

string thumbprint = x509.Thumbprint;
string thumbprint = x509.Thumbprint!;

UserIdentity certificateIdentity = await LoadUserCertificateAsync(thumbprint, "password", ct).ConfigureAwait(false);

Expand All @@ -158,7 +159,7 @@ public async Task RunAsync(CancellationToken ct)

m_logger.LogWarning(
"SECURITY-POLICY={SecurityPolicyUri} {SecurityMode}",
SecurityPolicies.GetDisplayName(ii.SecurityPolicyUri),
SecurityPolicies.GetDisplayName(securityPolicyUri),
ii.SecurityMode);

m_logger.LogWarning(
Expand Down Expand Up @@ -209,7 +210,7 @@ public async Task RunAsync(CancellationToken ct)

m_logger.LogWarning(
"SECURITY-POLICY={SecurityPolicyUri} {SecurityMode}",
SecurityPolicies.GetDisplayName(ii.SecurityPolicyUri),
SecurityPolicies.GetDisplayName(securityPolicyUri),
ii.SecurityMode);

m_logger.LogWarning(
Expand All @@ -222,15 +223,15 @@ public async Task RunAsync(CancellationToken ct)

m_logger.LogWarning(
"TEST COMPLETE: {SecurityPolicyUri} {SecurityMode}",
SecurityPolicies.GetDisplayName(ii.SecurityPolicyUri),
SecurityPolicies.GetDisplayName(securityPolicyUri),
ii.SecurityMode);

m_logger.LogWarning("{Line}", new string('=', 80));
}
}

Console.WriteLine("Ctrl-C to stop.");
m_quitEvent.WaitOne();
m_quitEvent!.WaitOne();
}
catch (Exception e)
{
Expand Down Expand Up @@ -258,7 +259,7 @@ internal async Task<SessionWrapper> RunTestAsync(
endpoint,
false,
false,
m_configuration.ApplicationName,
m_configuration.ApplicationName!,
600000,
//new UserIdentity(),
endpointDescription.SecurityMode != MessageSecurityMode.None ? identity : new UserIdentity(),
Expand Down Expand Up @@ -293,14 +294,14 @@ private async Task<UserIdentity> LoadUserCertificateAsync(
string password,
CancellationToken ct)
{
CertificateTrustList store = m_configuration.SecurityConfiguration.TrustedUserCertificates;
CertificateTrustList store = m_configuration.SecurityConfiguration.TrustedUserCertificates!;
#if NET8_0_OR_GREATER
// get user certificate with matching thumbprint
X509Certificate2Collection certificates =
await store.GetCertificatesAsync(m_telemetry, ct).ConfigureAwait(false);
X509Certificate2 hit = certificates
.Find(X509FindType.FindByThumbprint, thumbprint, false)
.FirstOrDefault();
.FirstOrDefault()!;

// create Certificate Identifier
var cid = new CertificateIdentifier(hit)
Expand Down Expand Up @@ -386,7 +387,7 @@ private void Session_KeepAlive(ISession session, KeepAliveEventArgs e)
// start reconnect sequence on communication error.
if (ServiceResult.IsBad(e.Status))
{
SessionReconnectHandler.ReconnectState state = m_reconnectHandler
SessionReconnectHandler.ReconnectState state = m_reconnectHandler!
.BeginReconnect(
m_wrapper.Session,
null,
Expand Down Expand Up @@ -420,7 +421,7 @@ private void Session_KeepAlive(ISession session, KeepAliveEventArgs e)
}
}

private void Client_ReconnectComplete(object sender, EventArgs e)
private void Client_ReconnectComplete(object? sender, EventArgs e)
{
// ignore callbacks from discarded objects.
if (!ReferenceEquals(sender, m_reconnectHandler))
Expand All @@ -431,11 +432,11 @@ private void Client_ReconnectComplete(object sender, EventArgs e)
lock (m_lock)
{
// if session recovered, Session property is null
if (m_reconnectHandler.Session != null)
if (m_reconnectHandler!.Session != null)
{
// ensure only a new instance is disposed
// after reactivate, the same session instance may be returned
if (!ReferenceEquals(m_wrapper.Session, m_reconnectHandler.Session))
if (!ReferenceEquals(m_wrapper!.Session, m_reconnectHandler.Session))
{
m_logger.LogInformation(
"--- RECONNECTED TO NEW SESSION --- {SessionId}",
Expand All @@ -461,7 +462,8 @@ private void Client_ReconnectComplete(object sender, EventArgs e)

private static string GetUserCertificateFile(string securityPolicyUri)
{
SecurityPolicyInfo securityPolicy = SecurityPolicies.GetInfo(securityPolicyUri);
// GetInfo returns null only for null/empty URI; caller passes a non-empty value.
SecurityPolicyInfo securityPolicy = SecurityPolicies.GetInfo(securityPolicyUri)!;

switch (securityPolicy.CertificateKeyAlgorithm)
{
Expand All @@ -480,16 +482,16 @@ private static string GetUserCertificateFile(string securityPolicyUri)

internal sealed class SessionWrapper : IUAClient
{
public ISession Session { get; init; }
public required ISession Session { get; init; }
}

private readonly Lock m_lock = new();
private SessionReconnectHandler m_reconnectHandler;
private ApplicationConfiguration m_configuration;
private SessionWrapper m_wrapper;
private SessionReconnectHandler? m_reconnectHandler;
private ApplicationConfiguration m_configuration = null!;
private SessionWrapper? m_wrapper;
private ILogger m_logger;
private ITelemetryContext m_telemetry;
private readonly ManualResetEvent m_quitEvent;
private readonly ManualResetEvent? m_quitEvent;

private const string kServerUrl = "opc.tcp://localhost:62541";
private const string kUserName = "sysadmin";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<Copyright>Copyright © 2004-2024 OPC Foundation, Inc</Copyright>
<RootNamespace>Quickstarts.ConsoleReferenceClient</RootNamespace>
<PublishAot Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net10.0'))">true</PublishAot>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\ConsoleReferenceServer\ConsoleUtils.cs" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
Expand Down
Loading
Loading