OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer
2.0.0-preview.2
Prefix Reserved
Requires NuGet 2.12 or higher.
dotnet add package OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer --version 2.0.0-preview.2
NuGet\Install-Package OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer -Version 2.0.0-preview.2
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer" Version="2.0.0-preview.2"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer" Version="2.0.0-preview.2" />
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer --version 2.0.0-preview.2
#r "nuget: OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer, 2.0.0-preview.2"
#:package OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer@2.0.0-preview.2
#addin nuget:?package=OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer&version=2.0.0-preview.2&prerelease
#tool nuget:?package=OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer&version=2.0.0-preview.2&prerelease
OPC UA migration analyzers, code fixers, source generator, and compatibility shim
What you get
A single NuGet install (OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer) that
ships three Roslyn components + a runtime shim to help migrate from OPC UA
.NET Standard 1.5.378 to 2.0:
- a Roslyn analyzer + code-fixer set (
UA0001–UA0022) that flags every pattern covered by the 2.0 migration guide and, where safe, applies the fix automatically; - a Roslyn source generator (
Opc.Ua.MigrationAnalyzer.Generator.dll) that emits per-consumerpublic sealed [Obsolete] class <Name>Collection : List<TElement>shims for every<Type>Collectionwrapper the consumer references but that 2.0 removed — including model-compiled<UserType>Collectionpatterns, not just the built-in ones. Element types renamed across the 1.5.378 → 2.0 boundary (DateTime→DateTimeUtc,Guid→Uuid,byte[]→ByteString,XmlElement→Opc.Ua.XmlElement) are pinned through a small override table; everything else (primitives, built-in unrenamed types, model-compiled user types) falls back to semantic lookup in the consumer's compilation; and - a compatibility shim assembly (
Opc.Ua.MigrationAnalyzer.Core.dll) that re-supplies the obsolete extension surface 2.0 moved or removed, so most consumer projects still compile after the upgrade.
ℹ The generator emits
publicshim types so legacy<Type>Collectionusage can continue compiling while you migrate incrementally. Keep treating each[Obsolete]+UA0002site as a migration step toList<T>/ArrayOf<T>.
How to migrate
Add the 2.0 OPC UA packages and the MigrationAnalyzer package to your consumer project:
<PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer" Version="x.y.z" PrivateAssets="all" />Run
dotnet build. Your code should compile: the shim covers the[Obsolete]extension surface that 2.0 moved or removed; the source generator covers<Type>Collectionwrappers; what remains are warnings rather than errors.Walk through the
UA00xxanalyzer warnings in the IDE and apply the offered auto-fixes. A handful (UA0001,UA0011,UA0015,UA0018,UA0021) areInfo-level and need a manual review. A single generator diagnostic (MIG01) fires when the generator can't resolve a model-compiled element type — add the appropriateusingor migrate the site manually.Once the project is warning-free, remove the
OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzerpackage reference. You are on clean 2.0 with no shim dependency.
Rules
| ID | Default | Replaces |
|---|---|---|
| UA0001 | Info | Utils.Trace / Utils.LogX |
| UA0002 | Warning | Removed <Type>Collection wrappers |
| UA0003 | Warning | x == null on now-struct built-in types |
| UA0004 | Warning | ?. on now-struct built-in types |
| UA0005 | Warning | byte[] where ByteString is now expected |
| UA0006 | Warning | new Variant(object\|DateTime\|Guid\|byte[]) |
| UA0007 | Warning | new NodeId(string) / new ExpandedNodeId(string) |
| UA0008 | Warning | Session.Call(..., params object[]) argument wrapping |
| UA0009 | Warning | [DataContract]/[DataMember] on configuration extensions |
| UA0010 | Warning | using/Dispose on CertificateIdentifier, UserIdentity, IUserIdentityTokenHandler |
| UA0011 | Info | Sync IUserIdentityTokenHandler.Encrypt/Decrypt/Sign/Verify |
| UA0012 | Warning | CertificateFactory.* static helpers |
| UA0014 | Warning | DataValue.IsGood(dv) static helper |
| UA0015 | Info | Sync / APM members on GDS / LDS clients |
| UA0018 | Info | CertificateIdentifier.Certificate getter |
| UA0019 | Warning | new DataValue(StatusCode[, ts]) |
| UA0020 | Warning | EncodeableFactory.GlobalFactory / Create() |
| UA0021 | Info | CertificateValidator / CertificateValidationEventArgs (structural rename in 1.6) |
| UA0022 | Warning | ApplicationConfiguration.CertificateValidator / ServerBase.CertificateValidator (renamed in 2.0 to .CertificateManager) |
What the shim provides
Opc.Ua.MigrationAnalyzer.Core.dll is delivered as a regular reference assembly and
re-exposes the 1.5.378 surface in two flavors:
- Moved obsolete extensions the 1.6 libraries no longer carry inline:
NodeId/Variant/DataValuenull-check helpers,Sessionsync helpers,Subscriptionsync helpers,ApplicationInstancehelpers,ServerBase.Start/Stop,TransportChannelAPM (BeginX/EndX),ChannelBasestatic factory methods, and similar surface. - New shims for genuinely-removed members:
EncodeableFactory.GlobalFactoryCertificateIdentifier.Certificate(throwsNotSupportedException)- sync wrappers for
IUserIdentityTokenHandler.{Encrypt,Decrypt,Sign,Verify} - sync + APM wrappers for the GDS / LDS client APIs.
What the shim does NOT cover
These changes are source-level only; no extension method can paper over them. Use the listed analyzer fix.
== null/!= nullon now-struct types — use the UA0003 fixer.?.member access on now-struct types — use the UA0004 fixer.using var x = new CertificateIdentifier(...)— use the UA0010 fixer to drop theusing/Disposecall.[DataContract]/[DataMember]on configuration extension classes — use the UA0009 fixer.- Removed
<Type>Collectionwrappers such asInt32Collection,NodeIdCollection, etc. — use the UA0002 fixer to rewrite toList<T>orArrayOf<T>.
Sync-over-async caveat
The sync shims (for example handler.Encrypt(bytes),
gdsClient.RegisterApplication(...), the Session / Subscription sync
helpers) wrap their *Async counterparts via
Task.Run(() => …Async(...)).GetAwaiter().GetResult(). This is intended as
a migration aid only: it keeps legacy call sites compiling while you port
them to async/await. Do not leave these calls on production hot paths —
follow the UA0011 / UA0015 guidance and switch to the async APIs.
TreatWarningsAsErrors recipe
If your project sets <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
and you cannot relax it during the migration window, exclude the migration
diagnostics from the failure set:
<PropertyGroup>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NoWarn>$(NoWarn);CS0618;UA0001;UA0002;UA0003;UA0004;UA0005;UA0006;UA0007;UA0008;UA0009;UA0010;UA0011;UA0012;UA0014;UA0015;UA0018;UA0019;UA0020</NoWarn>
</PropertyGroup>
Remove each entry as you finish fixing the corresponding rule, and drop the whole block once the MigrationAnalyzer package is removed.
Packaging note
The package ships three Roslyn component DLLs under
analyzers/dotnet/roslyn<major>.<minor>/cs/. The .NET SDK loads that folder when its
compiler supports the Roslyn API and ignores it otherwise, so an older host cleanly
skips the analyzer rather than failing to load it:
| Roslyn API | Minimum host |
|---|---|
| 4.14 | Visual Studio 2022 17.14 / .NET 9 SDK |
| 5.0 | Visual Studio 2026 18.0 / .NET 10 SDK |
Opc.Ua.MigrationAnalyzer.dll— the analyzer assembly. References onlyMicrosoft.CodeAnalysis.CSharpso it loads cleanly in csc.exe's analyzer host (which ships onlyMicrosoft.CodeAnalysis.dll+CSharp.dll, notWorkspaces). AllDiagnosticAnalyzertypes live here.Opc.Ua.MigrationAnalyzer.CodeFixer.dll— the code-fix assembly. ReferencesMicrosoft.CodeAnalysis.CSharp.Workspacesand hosts allCodeFixProvidertypes. Loaded only by Workspaces-aware hosts (Visual Studio /dotnet format).Opc.Ua.MigrationAnalyzer.Generator.dll— the source generator that emits the<Type>Collectionshims.
The analyzer / code-fix split is necessary because shipping a single DLL that
references Workspaces silently fails to load in csc.exe at command-line build time —
csc loads the assembly but JIT-resolution of Workspaces types fails (DLL not in
bincore), and the analyzer host swallows the load failure, producing zero diagnostics.
Splitting keeps the analyzer host happy while preserving full IDE/dotnet format
code-fix functionality.
RS1038 (suggesting separation) is the Roslyn rule that recommends this layout;
it is satisfied implicitly by the two-DLL design.
Suppression recipes
To suppress an individual rule for a single line:
#pragma warning disable UA0008 // Wrap Session.Call arguments with Variant.From
session.Call(objectId, methodId, "legacy");
#pragma warning restore UA0008
To set a project-wide severity, add to your .editorconfig:
[*.cs]
dotnet_diagnostic.UA0001.severity = none # silence UA0001 entirely
dotnet_diagnostic.UA0008.severity = error # treat UA0008 as an error
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| .NET Framework | net472 is compatible. net48 is compatible. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETFramework 4.7.2
- OPCFoundation.NetStandard.Opc.Ua.Client (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Configuration (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Core (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Core.Types (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Gds.Client.Common (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Types (>= 2.0.0-preview.2)
-
.NETFramework 4.8
- OPCFoundation.NetStandard.Opc.Ua.Client (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Configuration (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Core (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Core.Types (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Gds.Client.Common (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Types (>= 2.0.0-preview.2)
-
.NETStandard 2.1
- OPCFoundation.NetStandard.Opc.Ua.Client (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Configuration (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Core (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Core.Types (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Gds.Client.Common (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Types (>= 2.0.0-preview.2)
-
net10.0
- OPCFoundation.NetStandard.Opc.Ua.Client (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Configuration (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Core (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Core.Types (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Gds.Client.Common (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Types (>= 2.0.0-preview.2)
-
net8.0
- OPCFoundation.NetStandard.Opc.Ua.Client (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Configuration (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Core (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Core.Types (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Gds.Client.Common (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Types (>= 2.0.0-preview.2)
-
net9.0
- OPCFoundation.NetStandard.Opc.Ua.Client (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Configuration (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Core (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Core.Types (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Gds.Client.Common (>= 2.0.0-preview.2)
- OPCFoundation.NetStandard.Opc.Ua.Types (>= 2.0.0-preview.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.0-preview.2 | 40 | 8/24/2026 |