Как написать PowerShell CmdLet, который будет принимать параметр типа System.Type?

Я хочу передать Type к пользовательскому CmdLet, следующим образом:

PS> "1" | My-CmdLet -Check [System.String]

Я хочу использовать -Check параметр в качестве аргумента типа для -Is Оператор в моем CmdLet:

Function My-CmdLet {
    param(
        ${Actual},

        [System.String]
        ${Check}           # <-- I want to pass a type here
    )

    if (-not ($Actual -Is [Type] $Check)) {
        # ... 
    }
}

Когда вызывается следующим образом:

PS> My-CmdLet 1 -Check [System.String]

Результаты в ошибке:

Cannot convert the "[System.String]" value of type "System.String" to type  "System.Type". At MycmdLet.ps1:19 char:9
 +     if (-not ($Actual -Is [Type] $ExpectedType)) {
 +         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 + CategoryInfo          : InvalidArgument: (:) [], RuntimeException
 + FullyQualifiedErrorId : InvalidCastFromStringToType

Я пытался с помощью [System.String], [System.Type][System.Object], [System.RunTimeType] как тип для Check параметр, но ни один из тех, кажется, не работает.

Для сравнения:

Я могу передать тип командлету Where-Object следующим образом:

PS> Get-Process | Where-Object StartTime -Is [System.Datetime]

(В этом случае значение "[System.DateTime]" передается параметру CmdLet $Value который имеет тип [System.Object])

Я могу использовать тип с -Is Оператор, как это:

PS> "1" -Is [System.String]
True

Как мне объявить -Check параметр в моем CmdLet?

3 ответа

[System.String] (обратите внимание на квадратные скобки) является выражением, и поэтому оно не может быть значением параметра, не будучи заключенным в выражение группировки () или подвыражение $(), Это просто ярлык PowerShell для чего-то вроде [type]::GetType("System.String") (typeof() в с #).

System.String однако это строка, которую автоматическое преобразование типов PowerShell успешно преобразует в Type-объект.

function Test-Type
{
    param(
        [Parameter(Mandatory=$true,ValueFromPipeLine=$true)]
        [PSObject]$Object,
        [Parameter(Mandatory=$true)]
        [System.Type]$Type
    )

    $Object -is $Type
}

Test-Type "c" -Type ([string])
1 | Test-Type -Type string
1 | Test-Type -Type ([int])
"1" | Test-Type -Type string

#Output
True
False
True
True

В качестве альтернативы вы можете использовать строковый параметр и преобразовать его в Type-объект себя внутри своей функции. Таким образом, вы можете удалить квадратные скобки самостоятельно, чтобы преобразование типов работало. Как это:

function Test-Type
{
    param(
        [Parameter(Mandatory=$true,ValueFromPipeLine=$true)]
        [PSObject]$Object,
        [Parameter(Mandatory=$true)]
        [string]$Type
    )

    #Remove square brackets and convert to type-object
    $Type = [System.Type]($Type -replace '^\[(.*)\]$', '$1')

    $Object -is $Type
}

Test-Type "c" -Type [string]
1 | Test-Type -Type string
1 | Test-Type -Type [int]
"1" | Test-Type -Type string

#Output
True
False
True
True

По какой-то причине вы просто не объявите параметр типа System.Type на первом месте?

function Get-FullyQualifiedTypeName
{
    param([System.Type]$Type)

    Write-Host $Type.FullName
}

Если вы передаете фактический Type, это будет принято, в противном случае парсер попытается преобразовать вашу (частичную) строку типа имя в фактическую [type] для тебя. Не нужно повторно реализовывать то, что парсер уже делает для вас!

PS> Get-FullyQualifiedTypeName $([psobject])
System.Management.Automation.PSObject
PS> Get-FullyQualifiedTypeName string
System.String

Так что в вашем случае вы бы сделали что-то вроде

function Check-Type
{
    param(
        [Parameter(Mandatory,ValueFromPipeLine)]
        [psobject]$Actual,
        [Parameter(Mandatory)]
        [System.Type]$Check
    )

    $Actual -is $Check
}

Должен получить то, что вы хотите:

PS> "1" |Check-Type -Check string
True
PS> "1" |Check-Type -Check int
False
PS> 1 |Check-Type -Check int
True

Объявите параметр как строку и приведите его через [тип].

Например:

$a=1
$b="System.Int32"
$a -is [type]$b

Это должно вернуть $true.

Другие вопросы по тегам