To complement your own answer:
PowerShell class and enum definitions are parsed before execution begins and any types referenced in such definitions must either be:
loaded into the current session beforehand.
[only partially implemented in Windows PowerShell / in PowerShell (Core)] as of v7.3.x]
loaded via a using module / using assembly statement at the very
top of the file.
using module already works, but only if the referenced types are themselves PowerShell class / enum definitions.
As of PowerShell 7.3.x, types loaded from .NET assemblies - whether via a module containing assemblies imported with using module or using assembly to directly load an assembly - aren't yet detected.[1]
- See the following GitHub issues:
- #3461 (
using module) and #2074 (using assembly)
- #6652 - a meta issue tracking all class-related issues.
Allowing using assembly to detect .NET types at parse time has been green-lit in GitHub issue #3641, and the necessary work is being tracked as part of GitHub issue #6652 - but it is unclear when this will happen, given that the issue hasn't received attention in several years.
The workaround in the meantime is to load the referenced types via a separate script beforehand, by using the module manifest's NestedModules entry (which can also be used to dot-source *.ps1 files).
- Note: The
ScriptsToProcess entry would work too, but the scripts it references are dot-sourced in (loaded into the current scope of) the caller, not the enclosing module.
With types from compiled code (including ad hoc-compiled code with Add-Type), that works too, because such types invariably become available session-globally, but it is conceptually cleaner to use NestedModules, because it dot-sources scripts in the enclosing module's scope
Outside of modules, the workaround is similar:
Put your class definition in a separate .ps1 file.
In your main script, define or load the types that your class definition depends on, and then dot-source the separate script file, which ensures that all its dependent types have already been loaded.
In a pinch, you can also use Invoke-Expression (which should generally be avoided), as shown in this answer.
[1] Note that using Add-Type with -Assembly or -Path / -LiteralPath from inside the script is by definition not an option, because Add-Type only executes at runtime (rather than the using statements, which are evaluated at parse time), i.e. too late to load .NET types available up front. However, calling Add-Type from outside the target script, before the latter is invoked, does work.
Add-Typecommand isn't being executed.