在Powershell中将方法设置为对象的属性

时间:2019-10-02 12:05:04

标签: powershell

我有一个这样的对象数组

$all = @(
    @{ Name = 'First'; Method = { FirstMethod 1 }; Description = "First Description";  }
    @{ Name = 'Second'; Description = "Second Description" }
    @{ Name = 'Third'; Method = { ThirdMethod }; Description = "Third Description" }
)

每个对象都有一个名称(字符串),一个描述(字符串)和一个方法(其中包含一个函数及其可选)

FirstMethodSecondMethod看起来像这样:

Function FirstMethod
{
    param($number)
    Write-Host "$number - some other things"
    return $number
}

Function ThirdMethod
{
    Write-Host "Second called"
    return 'test'
}

我正在遍历$all中的所有项目,并尝试调用Method参数(如果存在)

Function RunAll
{
    foreach($item in $all)
    {
        If($item.Method)
        {
            Write-Host "It has method and its running it"
            $returned_from_method = $item.Method
            Write-Host "Value returned from method: $returned_from_method"
        }
        Else
        {
            Write-Host "Does not have a method!"
        }
    }
}

因此,我基本上需要的是:当循环位于数组First中的$returned_from_method = $item.Method项中时,它应该返回1(因为它调用FirstMethod并通过1.并且,当循环位于数组中的Third项中时,它应返回test(因为它调用了ThirdMethod)。

反正我能做到吗?

2 个答案:

答案 0 :(得分:2)

您发布的代码既没有定义(自定义)对象也没有方法。它定义了一个哈希表的列表,其中一个键具有脚本块值。在该键上使用点访问将仅返回脚本块的定义,而不调用它。

演示:

PS C:\> $ht = @{Name='foo'; Method={FirstMethod 1}; Description='bar'}
PS C:\> $ht.Method
FirstMethod 1

即使将哈希表转换为对象,该行为也不会改变:

PS C:\> $obj = [PSCustomObject]$ht
PS C:\> $obj.Method
FirstMethod 1

要实际调用脚本块,您需要调用脚本块的Invoke()方法:

PS C:\> $ht.Method.Invoke()
1 - some other things
1
PS C:\> $obj.Method.Invoke()
1 - some other things
1

在哈希表或对象的创建之前或之后定义脚本块中调用的函数,只要在调用脚本块之前定义该函数就无关紧要。您自己的答案中的代码似乎仅能工作,因为您用分组表达式(括号)替换了脚本块(花括号)。但是,这意味着“方法”是根据哈希表的定义进行评估的,并且仅函数的返回值与键一起存储。 Write-Host输出立即写入控制台,并且不与密钥一起存储。

PS C:\> $ht = @{Name='foo'; Method=(FirstMethod 1); Description='bar'}
1 - some other things
PS C:\> $ht.Method
1

要使用实际(脚本)方法创建对象,您需要添加具有正确类型的属性:

PS C:\> $obj | Add-Member -Name 'Method2' -Type ScriptMethod -Value {FirstMethod 2}
PS C:\> $obj.Method2()
2 - some other things
2

因此,用于创建对象的代码应如下所示:

$obj1 = [PSCustomObject]@{
    Name        = 'First'
    Description = 'First Description'
}
$obj1 | Add-Member -Name 'Method' -Type ScriptMethod -Value {FirstMethod 1}

$obj2 = [PSCustomObject]@{
    Name        = 'Second'
    Description = 'Second Description'
}

$obj3 = [PSCustomObject]@{
    Name        = 'Third'
    Description = 'Third Description'
}
$obj3 | Add-Member -Name 'Method' -Type ScriptMethod -Value {ThirdMethod}

$all = $obj1, $obj2, $obj3

答案 1 :(得分:-1)

如果有人为此而苦苦挣扎,这就是答案: 方法user.user_skill.skill_listsFirstMethod应该在数组之前声明 然后我需要在ThirdMethod而不是()中添加函数。

{}

现在工作正常!