如何编写将接受System.Type类型参数的PowerShell CmdLet?

时间:2016-02-27 11:29:16

标签: powershell types parameters parameter-passing cmdlet

我想将Type传递给自定义CmdLet,如下所示:

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

我想在我的CmdLet中使用-Check参数作为-Is运算符的类型参数:

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参数的类型,但这些似乎都不起作用。< / p>

进行比较:

我可以将类型传递给Where-Object cmdlet,如下所示:

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

(在这种情况下,值“[System.DateTime]”会传递给类型为$Value的CmdLet参数[System.Object]

我可以使用带有-Is运算符的Type,如下所示:

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

如何在我的CmdLet中声明-Check参数?

3 个答案:

答案 0 :(得分:1)

你有什么理由不首先声明System.Type类型的参数吗?

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

    Write-Host $Type.FullName
}

如果您传递实际的Type,它将被接受,否则,解析器将尝试将您的(部分)typename字符串解析为实际的[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

答案 1 :(得分:1)

[System.String](注意方括号)是一个表达式,因此它不能作为参数值而不包含在分组表达式()或子表达式$()中。它只是一个PowerShell快捷方式,例如[type]::GetType("System.String")(c#中的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

答案 2 :(得分:0)

将参数声明为字符串并通过[type]投射它。

例如:

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

这应该返回$ true。