具有New-Object

时间:2019-01-25 11:16:59

标签: powershell new-object

我一直在开发嵌套的字典数据结构,以构建文件列表,以供稍后在代码中使用。目前,我正在成功地使用它来创建空的数据结构。

$manageLocalAssets = @{
        resources = @{
            extra  = New-Object Collections.ArrayList
            new    = New-Object Collections.ArrayList
            skip   = New-Object Collections.ArrayList
            update = New-Object Collections.ArrayList
        }
        definitions = @{
            extra  = New-Object Collections.ArrayList
            new    = New-Object Collections.ArrayList
            skip   = New-Object Collections.ArrayList
            update = New-Object Collections.ArrayList
        }
    }

这可行,但是我想使用有序词典而不是哈希表,因此我可以按定义的顺序遍历数据。另外,我需要支持PS2.0(不要问),所以我不能使用[ordered]类型。

我尝试过

[Collections.Specialized.OrderedDictionary]$manageLocalAssets = @{
        resources = @{
            extra  = New-Object Collections.ArrayList
            new    = New-Object Collections.ArrayList
            skip   = New-Object Collections.ArrayList
            update = New-Object Collections.ArrayList
        }
        definitions = @{
            extra  = New-Object Collections.ArrayList
            new    = New-Object Collections.ArrayList
            skip   = New-Object Collections.ArrayList
            update = New-Object Collections.ArrayList
        }
    }

我已经尝试过

$manageLocalAssets = [Collections.Specialized.OrderedDictionary]@{
        resources = @{
            extra  = New-Object Collections.ArrayList
            new    = New-Object Collections.ArrayList
            skip   = New-Object Collections.ArrayList
            update = New-Object Collections.ArrayList
        }
        definitions = @{
            extra  = New-Object Collections.ArrayList
            new    = New-Object Collections.ArrayList
            skip   = New-Object Collections.ArrayList
            update = New-Object Collections.ArrayList
        }
    }

都无法将哈希表转换为有序字典。我唯一的选择是这样的丑陋(IMO)

$manageLocalAssets = New-Object Collections.Specialized.OrderedDictionary
$manageLocalAssets.Add('resources', (New-Object Collections.Specialized.OrderedDictionary))
$manageLocalAssets.resources.Add('extra', (New-Object Collections.ArrayList))

[ss64] [1]让我想到-财产可能是答案,这似乎很接近

$manageLocalAssets = New-Object Collections.Specialized.OrderedDictionary -property @{
        resources = New-Object Collections.Specialized.OrderedDictionary -property @{
            extra  = New-Object Collections.ArrayList
            new    = New-Object Collections.ArrayList
            skip   = New-Object Collections.ArrayList
            update = New-Object Collections.ArrayList
        }
        definitions = New-Object Collections.Specialized.OrderedDictionary -property @{
            extra  = New-Object Collections.ArrayList
            new    = New-Object Collections.ArrayList
            skip   = New-Object Collections.ArrayList
            update = New-Object Collections.ArrayList
        }
    }

但是它无法创建嵌套键,额外键,跳过键等。我朝着正确的方向前进,还是我最好只接受一堆单独的New-Object和.Add行?

编辑#1:我有一个想法,因为从最深层次上讲,数据结构是相同的,所以我尝试了

$assets = New-Object Collections.Specialized.OrderedDictionary -property @{
        extra  = New-Object Collections.ArrayList
        new    = New-Object Collections.ArrayList
        skip   = New-Object Collections.ArrayList
        update = New-Object Collections.ArrayList
    }
    $manageLocalAssets = New-Object Collections.Specialized.OrderedDictionary -property @{
        resources = $assets
        definitions = $assets
    }

奇怪的是,错误是

New-Object : The member "skip" was not found for the specified .NET object.
At \\Mac\Support\Px Tools\Dev 4.0\Resources\PxContext_Machine.ps1:413 char:15
+ ...   $assets = New-Object Collections.Specialized.OrderedDictionary -pro ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [New-Object], InvalidOperationException
    + FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.NewObjectCommand

New-Object : The member "resources" was not found for the specified .NET object.
At \\Mac\Support\Px Tools\Dev 4.0\Resources\PxContext_Machine.ps1:419 char:26
+ ... calAssets = New-Object Collections.Specialized.OrderedDictionary -pro ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [New-Object], InvalidOperationException
    + FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.NewObjectCommand
  [1]: https://ss64.com/ps/new-object.html

413 $assets = New-Object Collections.Specialized.OrderedDictionary -property @{行,而 419 $manageLocalAssets = New-Object Collections.Specialized.OrderedDictionary -property @{行。

因此,似乎首先要处理多余的内容和新内容,然后在第一个任务中跳过失败,而在第二个任务中资源立即失效。

编辑#2:因此,将重复部分分解为不同的变量会使我想到这一点

$assets = New-Object Collections.Specialized.OrderedDictionary
$assets.Add('extra', (New-Object Collections.ArrayList))
$assets.Add('new', (New-Object Collections.ArrayList))
$assets.Add('skip', (New-Object Collections.ArrayList))
$assets.Add('update', (New-Object Collections.ArrayList))

$manageLocalAssets = New-Object Collections.Specialized.OrderedDictionary
$manageLocalAssets.Add('resources', $assets)
$manageLocalAssets.Add('definitions', $assets)

实际上,这是更少的行,并且当我添加到$ manageLocalAssets时,效率会更高。它在外观上看起来不像我的其他数据结构初始化,但是我想我很快就会习惯这一点。而且它使我可以使用这样的循环结构以所需的顺序处理数据。

foreach ($asset in $manageLocalAssets.keys) {
    foreach ($key in ($manageLocalAssets.$asset).keys) {
        Write-Host "$asset $key"
        foreach ($file in $manageLocalAssets.$asset.$key) {
            Write-Host " $file"
        }
    }
}

这不是“理想”,但理想状态在这里意味着“熟悉”,这不是做出决定的重要理由。

编辑#3:不。我错了。实际上,这会使$manageLocalAssets.resources$manageLocalAssets.definitions的内容相同,即$ assets变量。似乎我还在寻找。

1 个答案:

答案 0 :(得分:1)

我认为向后兼容永远不会很漂亮?这是我能想到的最好的方法,有点接近结构化定义(使用简单数组):

$definition = ((
"resources", (
    "extra",
    "new",
    "skip",
    "update"
)), (
"definitions", (
    "extra",
    "new",
    "skip",
    "update"
)))
$manageLocalAssets = New-Object System.Collections.Specialized.OrderedDictionary
$definition | foreach {
    $sub = New-Object System.Collections.Specialized.OrderedDictionary
    $_[1] | foreach {
        $sub.Add($_, (New-Object Collections.ArrayList))
    }
    $manageLocalAssets.Add($_[0], $sub)
}

当然,您也可以将实际值(ArrayList)放入数组定义中,但是我想那会写很多东西,而且看起来也不漂亮。

替代解决方案,使用函数从定义中创建具有可变级别的有序字典。较为冗长但可重复使用:

function New-OrderedDictionary ($definition) {
    $dict = New-Object System.Collections.Specialized.OrderedDictionary
    foreach ($item in $definition) {
        $key, $value = $item[0, 1]
        # you might want to change this check,
        # depending on how you want to built the definition
        if ($value.Count -gt 0) {
            $value = New-OrderedDictionary $value
        }
        $dict.Add($key, $value)
    }
    return $dict
}

$manageLocalAssets = New-OrderedDictionary ((
    "resources", (
        ("extra" , (New-Object System.Collections.Specialized.OrderedDictionary)),
        ("new"   , (New-Object System.Collections.Specialized.OrderedDictionary)),
        ("skip"  , (New-Object System.Collections.Specialized.OrderedDictionary)),
        ("update", (New-Object System.Collections.Specialized.OrderedDictionary))
    )), (
    "definitions", (
        ("extra" , (New-Object System.Collections.Specialized.OrderedDictionary)),
        ("new"   , (New-Object System.Collections.Specialized.OrderedDictionary)),
        ("skip"  , (New-Object System.Collections.Specialized.OrderedDictionary)),
        ("update", (New-Object System.Collections.Specialized.OrderedDictionary))
)))