Migrate OPC UA .NET Standard applications from version 1.5.378 to
version 2.0.x. Walks consumers through installing the
OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer NuGet (analyzers UA0001-UA0022,
source-generated <Type>Collection shims, runtime compat shim), running
`dotnet format analyzers` to apply auto-fixes, and walking the residual manual
patterns. Use when asked to "migrate to v20", "update from 1.5.378", "fix
v20 build errors", "migrate OPC UA code to 2.0", "update to new Variant API",
"fix ArrayOf migration", "update NodeId readonly struct", "migrate from object
to Variant", "fix CS0246 on <Type>Collection wrappers", "fix CS0246 on
CertificateValidator", or "address UA00xx / MIG01 warnings". Sample triggers:
user says "my project targets 1.5.378 and I need to update to v20"; user
provides build errors after updating NuGet packages to 2.0; user asks "how do
I update my custom NodeManager for v20?"; user says "fix all the CS0029
errors after upgrading to v20".
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Migrate OPC UA .NET Standard applications from version 1.5.378 to
version 2.0.x. Walks consumers through installing the
OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer NuGet (analyzers UA0001-UA0022,
source-generated <Type>Collection shims, runtime compat shim), running
`dotnet format analyzers` to apply auto-fixes, and walking the residual manual
patterns. Use when asked to "migrate to v20", "update from 1.5.378", "fix
v20 build errors", "migrate OPC UA code to 2.0", "update to new Variant API",
"fix ArrayOf migration", "update NodeId readonly struct", "migrate from object
to Variant", "fix CS0246 on <Type>Collection wrappers", "fix CS0246 on
CertificateValidator", or "address UA00xx / MIG01 warnings". Sample triggers:
user says "my project targets 1.5.378 and I need to update to v20"; user
provides build errors after updating NuGet packages to 2.0; user asks "how do
I update my custom NodeManager for v20?"; user says "fix all the CS0029
errors after upgrading to v20".
license
MIT
compatibility
Requires .NET SDK 9.0.100+ (10.0.300+ for the `dotnet format analyzers`
auto-fix pass), a C# project, and resolvable access to the
OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer NuGet package (v2.0.*-*).
IDE auto-fixes need a Workspaces-aware host (Visual Studio, Rider, or
`dotnet format`). Generator + analyzers load in csc.exe too.
Upgrade existing OPC UA .NET Standard consumer projects from 1.5.378
(master378) to 2.0.x (master). The skill assumes you already have a working
1.5.378 codebase; it does not teach OPC UA from scratch.
Migration sub-doc index — load only what you need
Context-efficiency rule. The full migration content is no longer in
a single ~150 KB document; it is split across 12 thematic sub-docs under
docs/migrate/2.0.x/.
Do not load docs/MigrationGuide.md into context — it is now a thin
landing page. Instead, match the user's symptom to a row below and load
the single sub-doc named in that row.
When the user hits…
Load only
CS0029 / CS1503 / CS0266 on NodeId, Variant, DataValue, ExtensionObject, QualifiedName, LocalizedText, ArrayOf<T> / MatrixOf<T>, ByteString, StatusCode, XmlElement, EnumValue, or [Obsolete] on built-in type APIs (analyzer UA0001–UA0020)
If the user's symptom does not obviously map to one row, read
docs/migrate/2.0.x/README.md (small —
the same table plus a short intro) and pick from there. Avoid loading
multiple sub-docs unless the symptom genuinely spans two areas (for
example, node-states.mdandtypes.md when a NodeManager runs into
both INodeManager3 adoption and Variant-for-object API changes).
Level 1: Quick Start (5 minutes)
What you'll do
Install one NuGet, bump the OPC UA package versions, build once, apply the
analyzer auto-fixes, walk the handful of manual residuals, then remove the
migration NuGet. The package ships three Roslyn components and a runtime
compat shim that together cover most mechanical migration patterns
automatically.
Core principles
Install before editing. Get the migration NuGet into the project before
you start fixing build errors. The source generator turns CS0246 ("type
<Type>Collection not found") into [Obsolete] warnings + UA0002
diagnostics, and the runtime shim turns "method removed" errors into
[Obsolete] warnings too. Edit a working build, not a broken one.
Let tooling do the mechanical work. 14 of the 19 UA00xx rules have
auto-fixes — apply them via the IDE quick-fix or dotnet format analyzers
before opening a single file by hand.
Reserve human judgement for the 5 manual rules — UA0001 (telemetry
plumbing), UA0011 / UA0015 (sync→async promotion), UA0018 (cert load
refactor), UA0021 (CertificateValidator structural rewrite).
Remove the migration NuGet at the end. It is a PrivateAssets="all"
build-only dependency; once warning-free, drop the reference and you're on
clean 2.0 with zero shim dependency.
Quick reference
<!-- 1. In every csproj that references OPCFoundation.NetStandard.Opc.Ua.*, bump
the OPC UA package version and add this one extra reference: --><ItemGroup><PackageReferenceInclude="OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer"Version="2.0.*-*"PrivateAssets="all" /></ItemGroup>
# 2. Restore + build. Code that was hard-broken on 1.5.378 → 2.0 now compiles# with [Obsolete] warnings + UA00xx + (rarely) MIG01 diagnostics.
dotnet restore
dotnet build
# 3. Apply all auto-fix rules in one pass:
dotnet format analyzers <YourSolution>.sln \
--diagnostics UA0002 UA0003 UA0004 UA0005 UA0006 UA0007 UA0008 \
UA0009 UA0010 UA0012 UA0014 UA0019 UA0020 UA0022 \
--severity warn
# 4. Walk the residual UA0001 / UA0011 / UA0015 / UA0018 / UA0021 by hand.# See references/migration-patterns.md for the categorical playbook.# 5. Once the build is warning-free, drop the package reference. You're done.
Essential checklist
Every <PackageReference Include="OPCFoundation.NetStandard.Opc.Ua.*"> bumped to 2.0.*-*
OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer added as PrivateAssets="all" build-only dependency in every consumer project
[Obsolete] (CS0612/CS0618) warnings fixed, not suppressed
MigrationAnalyzer package reference removed before merging
Common pitfalls
Do not suppress [Obsolete] or UA00xx warnings. Obsolete API will be
removed in the next minor 2.0 release; if you <NoWarn> it now, your build
will break on upgrade.
Public APIs returning a generated <Type>Collection shim trip CS0050
("inconsistent accessibility"). The generator emits internal types by
design. The fix is to migrate the public-API signature to List<T> /
ArrayOf<T> first; internal call sites can keep the shim while you iterate.
Legacy .NET Frameworkxmlns="http://schemas.microsoft.com/developer/msbuild/2003"
projects ignore Directory.Build.targets<PackageReference> injection. Add
the migration package directly into the legacy csproj's existing <ItemGroup>.
TreatWarningsAsErrors=true blocks the warning-driven workflow. Use the
NoWarn recipe in assets/Directory.Build.targets.example.xml for the
migration window, then peel each entry back as you fix the rule.
The legacy Quickstarts.Servers meta-package does not exist on 2.0. If
your project depends on it, switch to a <ProjectReference> to
samples/Quickstarts.Servers or to an equivalent project of your own.
Level 2: Implementation (30 minutes)
What the migration package ships
The single OPCFoundation.NetStandard.Opc.Ua.MigrationAnalyzer NuGet contains
three Roslyn components plus a runtime compat shim:
Component
Where
Loaded by
Purpose
Opc.Ua.MigrationAnalyzer.dll
analyzers/dotnet/roslyn4.14/cs/ and roslyn5.0/cs/
csc.exe and IDE
19 DiagnosticAnalyzers (UA0001–UA0022). No Workspaces reference, csc-safe.
Opc.Ua.MigrationAnalyzer.CodeFixer.dll
analyzers/dotnet/roslyn4.14/cs/ and roslyn5.0/cs/
Workspaces-aware hosts only (Visual Studio, Rider, dotnet format analyzers)
14 CodeFixProviders.
Opc.Ua.MigrationAnalyzer.Generator.dll
analyzers/dotnet/roslyn4.14/cs/ and roslyn5.0/cs/
csc.exe and IDE
IIncrementalGenerator that emits internal sealed [Obsolete] class <Name>Collection : List<TElement> shims into the consumer compilation for every <Type>Collection reference that fails to bind.
Re-supplies the obsolete extension surface 2.0 moved or removed so 1.5.378 call sites continue to compile with [Obsolete] warnings.
The 19 analyzer rules at a glance
The full table with default severity, replaces, auto-fix status, and
before/after examples lives in
references/analyzer-rules.md. One-line summary
of where each lands in the workflow:
The generator can't uniquely resolve the element type for a <Foo>Collection reference (0 or > 1 candidates in the compilation). Add a using for the namespace defining Foo, or migrate the call site manually. See references/source-generator.md.
Source-generated <Type>Collection shims
When 2.0 deleted the <Type>Collection wrapper types, every consumer call site
like new Int32Collection { 1, 2, 3 } and IList<NodeIdCollection> nodes
became a hard CS0246 ("type or namespace not found"). The package's source
generator (MigrationGenerator) closes this gap: for every short name ending in
Collection that doesn't bind, it emits an internal sealed [Obsolete] class <Name>Collection : List<TElement> into the consumer's compilation.
Built-in catalog (rename overrides) pins element types that renamed
across the 1.5.378 → 2.0 boundary, where semantic lookup would resolve to
the wrong type or fail with ambiguity: DateTime→DateTimeUtc, Guid→Uuid,
byte[]→ByteString, XmlElement→System.Xml.XmlElement (the latter
disambiguates against the new Opc.Ua.XmlElement). The generator uses these
over whatever the consumer's compilation resolves.
Arbitrary <UserType>Collection patterns (model-compiler output, vendor
structures, etc.) are resolved by stripping the Collection suffix and
looking up the resulting short name in the consumer's compilation via
Compilation.GetSymbolsWithName. Exactly one match → emit; zero or many →
MIG01.
Implicit conversion to ArrayOf<TElement> on every generated type so
2.0 APIs that took ArrayOf<T> keep accepting the shim instance.
internal sealed — the shim never leaks through the consumer's public
API surface (intentional; see "Common pitfalls" above for the CS0050
consequence).
Opc.Ua.MigrationAnalyzer.Core.dll re-exposes the 1.5.378 obsolete extension
surface (via C# 14 extension members) so 1.5.378-style call sites continue to
compile. Coverage and the sync-over-async caveat are documented in
references/runtime-shim.md.
Manual residuals — priority order
For the 5 rules without auto-fixes and the patterns the analyzer doesn't catch
at all (e.g. Variant.Value setter type changes, BaseVariableState.Value
becoming Variant, INodeManager covariant return changes), apply fixes in
this order to minimize cascading errors:
If your project sets <TreatWarningsAsErrors>true</TreatWarningsAsErrors> and
you can't relax it during the migration window, exclude the migration diagnostics
from the failure set in your Directory.Build.targets:
Pasteable file at assets/Directory.Build.targets.example.xml.
Peel each entry back as you fix the rule; drop the whole block once the
MigrationAnalyzer package is removed.
Known compatibility gaps
Legacy .NET Framework WinForms projects in pre-SDK MSBuild XML format
(xmlns="…/2003") — <PackageReference> injection via
Directory.Build.targets is silently ignored; the migration package must be
added inline to each csproj.
The OPCFoundation.NetStandard.Opc.Ua.Quickstarts.Servers meta-package is
not published on 2.0 — consumers must switch to a <ProjectReference> to
samples/Quickstarts.Servers or an equivalent first-party project.
Public APIs returning a <Type>Collection will hit CS0050 because the
generator's shim is internal by design — migrate the public surface to
List<T> / ArrayOf<T> first.
Target framework, .NET SDK, and Roslyn API requirements (and how to verify
analyzers actually loaded under csc.exe) are documented in
references/compatibility-matrix.md.
Level 3: Mastery (Extended Learning)
The references/ and scripts/ folders in this skill contain the extended
material. Load them on demand via your agent runtime's
read_skill_resource / run_skill_script tools: