How do I conditionally add a class with Add-Type -TypeDefinition if it isn't added already?
Solution 1:
This technique works well for me:
if (-not ([System.Management.Automation.PSTypeName]'MyClass').Type)
{
Add-Type -TypeDefinition 'public class MyClass { }'
}
- The type name can be enclosed in quotes 'MyClass', square brackets [MyClass], or both '[MyClass]' (v3+ only).
- The type name lookup is not case-sensitive.
- You must use the full name of the type, unless it is part of the System namespace (e.g. [System.DateTime] can be looked up via 'DateTime', but [System.Reflection.Assembly] cannot be looked up via 'Assembly').
- I've only tested this in Win8.1; PowerShell v2, v3, v4.
Internally, the PSTypeName class calls the LanguagePrimitives.ConvertStringToType() method which handles the heavy lifting. It caches the lookup string when successful, so additional lookups are faster.
I have not confirmed whether or not any exceptions are thrown internally as mentioned by x0n and Justin D.
Solution 2:
Actually, none of this is required. Add-Type maintains a cache of any code that you submit to it, along with the resulting type. If you call Add-Type twice with the same code, then it won't bother compiling the code and will just return the type from last time.
You can verify this by just running an Add-Type call twice in a row.
The reason you got the error message in the example above is that you changed the code between calls to Add-Type. While the solution above makes that error go away in this situation, it also means that you're working with an older definition of the type that probably isn't acting the way you think it is.
Solution 3:
There's a nicer way to do this without incurring the cost of exceptions:
if (-not ("MyClass" -as [type])) {
add-type @"
public class MyClass { }
"@
}
update: well, apparently powershell signals internally with an exception anyway. It has a bad habit of doing this. The interpreter uses SEH to signal with the break
and continue
keywords, for example.
Solution 4:
The simplest way to do this is a try/catch block. You have two options for doing this:
try { [MyClass] | Out-Null } catch { Add-Type -TypeDefinition $csharpString; }
try { Add-Type -TypeDefinition $csharpString; } catch {}