Ошибка вызова метода, поскольку [System.Collections.ObjectModel.Collection`1 [[]] не содержит метод, который я добавил в pscustomobject. - PullRequest
0 голосов
/ 09 января 2019

У нас есть файл json, который содержит массив с продуктами с ценой продажи и для некоторых (продуктов, которые мы должны купить) номер детали и цену покупки. Например:

{
"Prices":[
    {
        "Product":"AD User",
        "Price":3.52
    },
    {
        "Product":"Skype for Business Plus SAL",
        "Price":4.68,
        "Part number":"6SH-00002",
        "Buy price":3.90
    },
    {
        "Product":"Citrix CAL",
        "Price":6.40,
        "Part number":"ROYSPLACXABASE",
        "Buy price":5.33
    }
    ]
}

Я использую следующий код для извлечения содержимого json и для каждого объекта с номером детали помещаю объект в массив PSCustomObjects и добавляю int OrderCount и функцию для увеличения этого OrderCount:

$PurchaseOrder = @()
[object[]]$Prices = Get-Content 'C:\Pricelist.json' | Out-String | ConvertFrom-Json
foreach($_price  in ($Prices.prices | Where-Object {$_."Part Number"})){ 
    $PurchaseOrderItem = $_price.psobject.copy()
    $PurchaseOrderItem | Add-Member -Name "OrderCount" -MemberType NoteProperty -Value 0
    $PurchaseOrderItem | Add-Member -MemberType ScriptMethod -Name IncrementOrderCount {
        param([int]$amount)
        $this.OrderCount = $this.OrderCount + $amount
    }
    $PurchaseOrder += $PurchaseOrderItem
}

Если выяснилась следующая функция для обновления $ PurchaseOrder:

function Update-PurchaseOrder{
    [Cmdletbinding()]
    param(
        [ref]$PurchaseOrder,
        [string]$ProductName,
        [int]$Count
    )

    $PurchaseOrder.Value.where({$_.Product -eq $ProductName}).IncrementOrderCount($Count)
}

Вместо этого я получаю следующую ошибку при запуске этой функции

Update-PurchaseOrder -PurchaseOrder ([ref]$PurchaseOrder) -ProductName "Citrix CAL" -Count 5

Method invocation failed because [System.Collections.ObjectModel.Collection`1[[System.Management.Automation.PSObject, System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]] does not contain a
method named 'IncrementOrderCount'.
At line:9 char:5
+     $PurchaseOrder.Value.where({$_.Name -eq $ProductName}).IncrementO ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

Если я запускаю этот код с $Prices объектом, который создается вручную, например:

$Prices = @([pscustomobject]@{Product="Product1";Price=1},[pscustomobject]@{Product="Product2";Price=2})

Он работает без проблем. Я пытался привести несколько объектов к разным типам, но у меня нет выбора.


Я добавил дополнительный фрагмент кода, чтобы проверить, существует ли Продукт в моем PurchaseOrder, теперь он работает без проблем.

Write-Verbose "Updating PurchaseOrder for product $Title "
if($PurchaseOrder.Value.where({$_.Product -eq $Title})){
    try{
        $PurchaseOrder.Value.where({$_.Product -eq $Title}).IncrementOrderCount($Count)
    } catch {
        Write-Warning "Error while incrementing OrderCount for product $($Title): $($_.Exception.Message)"
    }
} else {
    Write-Verbose "Product $Title not found in PurchaseOrder."
}

1 Ответ

0 голосов
/ 09 января 2019

Используйте ForEach-Object, чтобы выполнить итерацию по коллекции, а затем вызвать метод для каждого объекта.

Также свойство с именем продукта является Product вместо имени.

function Update-PurchaseOrder{
    [Cmdletbinding()]
    param(
        [ref]$PurchaseOrder,
        [string]$ProductName,
        [int]$Count
    )

    $PurchaseOrder.Value.where({$_.Product -eq $ProductName}) | ForEach-Object {$_.IncrementOrderCount($Count)}
}

Также я считаю, что $PurchaseOrder уже будет передан по ссылке, чтобы вы могли пропустить лишние хлопоты и просто передать $PurchaseOrder вместо ([ref]$PurchaseOrder). И тогда не нужен дополнительный шаг распаковки значения в функцию.

...