Reputation: 410
I want to check is some type exist. For example:
Add-Type -TypeDefinition '
public class Test{
public static int aaa(){
return 1;
}
}'
[test]::aaa() # 1
[type]::GetType('test') # empty
but GetType() not works for my 'test' type.
Upvotes: 2
Views: 1303
Reputation: 437743
To complement Theo's helpful answer, which undoubtedly shows the best solution (-as [Type]
), with why [Type]::GetType('Test')
failed:
System.Type.GetType()
only finds types from assemblies that were loaded from or saved to disk - that is, types either loaded from preexisting assembly files or types in dynamically created assemblies also, optionally, persisted to disk.
By contrast, when you define types dynamically in PowerShell, they are created in dynamic, in-memory assemblies that are not persisted to disk, so [Type]::GetType()
doesn't see them. Note that this applies equally to:
Types created with Add-Type
-TypeDefinition
or -MemberDefinition
Types created with the (PSv5+) class
and enum
keywords, i.e. custom PowerShell classes and enumerations.
However, [Type]::GetType()
offers overloads that enable hooking custom assembly-resolver functionality into the type-lookup process, i.e. a way to look for types in assemblies in additional places.
This is presumably what PowerShell uses behind the scenes to include its dynamic in-memory-only assemblies in the lookup process, which comes into play in the following contexts (case-insensitively, as PowerShell generally is):
In the most obvious form, in type literals ([<typeName>]
), so that you can refer to your Test
type as [Test]
, for instance.
Such type literals therefore also work with -is
, the type(-inheritance) / interface test operator, so you can test a given object for being of or deriving from the given type / implementing the given interface type.
Caveat: If the type name inside [...]
isn't recognized as a loaded or dynamically declared type, an exception occurs, which surfaces as a statement-terminating error in PowerShell.
In the context of -as
, the conditional type conversion operator, as shown in Theo's answer ('<typeName>' -as [type]
), where [type]
refers again to System.Type
.
[Test]
, in your example); if not, $null
is returnedif
conditional, a type-information object getting returned is implicitly $true
, where as $null
is implicitly $false
- see the bottom section of this answer for the exact rules of implicit to-Boolean conversion), so the -as [type]
approach is the most convenient way to test a type's presence.When you cast a type-name string to [type]
: [type] 'Test'
-as
approach, this approach triggers an exception that surfaces as a statement-terminating error in PowerShell.if ('Test' -as [type]) ...
isif ($(try { [type] 'Test' } catch { $null })) ...
A note re namespaces:
Types created with class
and enum
have no namespace component, so it is sufficient to refer to the types by their own name alone, such as [Test]
in the case at hand.
Types created via Add-Type
:
via -TypeDefinition
(arbitrary C# code):
namespace <identifier> { ... }
construct or not.via -MemberDefinition
(C# code for declaring static methods, typically for P/Invoke calls):
You do need a namespace qualifier to refer to the resulting type, namely either the one you've specified explicitly via the -Namespace
parameter or the the implicitly used Microsoft.PowerShell.Commands.AddType.AutoGeneratedTypes.WinApi
namespace.
You can bypass having to refer to the type by namespace-qualified name by using the -PassThru
switch and saving the type-definition object in a variable, which allows you to call its static methods directly via that variable.
Upvotes: 3
Reputation: 61068
You can test if the type already exists with
if (-not ('Test' -as [type])) {
# or
# if (-not ([System.Management.Automation.PSTypeName]'Test').Type) {
Add-Type -TypeDefinition '
public class Test{
public static int aaa(){
return 1;
}
}'
}
I don't know why [type]::GetType('test')
doesn't work though, but
("Test" -as [type])
does work and returns either $null or
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True False Test System.Object
Upvotes: 3