Вопрос создания пользовательского класса Powershell - PullRequest
0 голосов
/ 31 августа 2018

По мере развития PowerShell и изучения пользовательских классов, я продолжаю использовать это странное исключение, которое сохраняется до тех пор, пока я не внесу какие-либо изменения.

> PS C:\Users\Purpl_000> C:\PS\Node\NodeTest.ps1 Cannot convert the
> "Node" value of type "Node" to type "Node". At
> C:\PS\Node\NodeTest.ps1:5 char:1
> + [Node]$node1 = New-Object Node -Property @{Next=$null; Value=3};
> + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     + CategoryInfo          : MetadataError: (:) [], ArgumentTransformationMetadataException
>     + FullyQualifiedErrorId : RuntimeException   Exception setting "Next": "Cannot convert the "Node" value of type "Node" to type
> "Node"." At C:\PS\Node\NodeTest.ps1:9 char:1
> + $node2.Next = $node1;
> + ~~~~~~~~~~~~~~~~~~~~
>     + CategoryInfo          : NotSpecified: (:) [], SetValueInvocationException
>     + FullyQualifiedErrorId : ExceptionWhenSetting   New-Object : The value supplied is not valid, or the property is read-only. Change the
> value, and then try again. At C:\PS\Node\NodeTest.ps1:13 char:16
> + [Node]$node3 = New-Object Node -Property @{Next=$node2; Value=9};
> +                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     + CategoryInfo          : InvalidData: (:) [New-Object], Exception
>     + FullyQualifiedErrorId : SetValueException,Microsoft.PowerShell.Commands.NewObjectCommand  
> Cannot find an overload for "new" and the argument count: "2". At
> C:\PS\Node\NodeTest.ps1:22 char:1
> + [Node]$node4 = [Node]::new($node3, 12);
> + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     + CategoryInfo          : NotSpecified: (:) [], MethodException
>     + FullyQualifiedErrorId : MethodCountCouldNotFindBest

Вот Node.ps1

class Node
{
    [Node]$Next;
    [int]$Value;

    # .ctor
    Node([Node]$next, [int]$value)
    {
        $this.Next = $next;
        $this.Value = $value;
    }

    # default .ctor
    Node() {}


    static [int] Method1([Node]$n1)
    {
        return $n1.Value;
    }

    static [Node] Method2([Node]$n2)
    {
        $n2.Value = $n2.Value + 5;
        return $n2.Value;
    }
}

Вот NodeTest.ps1

. 'C:\PS\Node\Node.ps1';

[Node]$node1 = New-Object Node -Property @{Next=$null; Value=3};
[Node]$node2 = [Node]::new();
$node2.Next = $node1;
$node2.Value = 5;

[Node]$node3 = New-Object Node -Property @{Next=$node2; Value=9};

[Node]$node4 = [Node]::new($node3, 12);

Я работаю в PowerShell ISE. Node.ps1 сохранен и успешно запущен. NodeTest.ps1 также сохраняется, но дует иногда вверх до Я делаю любые кажущиеся не относящимися к делу изменения в файле, сохраняю, затем Запускаю сценарий снова. В этот момент все снова работает нормально. Примеры изменений, которые разрешили проблему: (1) добавление дополнительной строки пробела, (2) удаление дополнительной строки пробела, (3) добавление комментария и т. Д.

Я понимаю

New-Object : The value supplied is not valid, or the property is read-only. Change the value, and then try again.

через мое тестирование того, что происходит, когда вы используете неправильные типы, но не совсем уверен, почему я периодически вижу это. Простой пример намеренного повторения этой ошибки путем передачи int , где ожидается Node . :)

[Node]$node3 = New-Object Node -Property @{Next=5; Value=9};

Следующие слова меня смущают. Как Node не может быть Node , а затем волшебным образом Node снова после добавления пустой строки в NodeTest.ps1 ?

Exception setting "Next": "Cannot convert the "Node" value of type "Node" to type "Node"."

Любая информация, объяснения или образование будут чрезвычайно признательны!

Спасибо всем! Michael

1 Ответ

0 голосов
/ 31 августа 2018

Я думаю, что проблема связана с наличием объектов типа [node] в текущем сеансе powershell, а затем с переопределением типа [node]. Кажется, есть определенные определения [node] в зависимости от содержимого файла.

То, что может помочь сделать это немного яснее, использует [node].guid, чтобы увидеть четкие определения вашего класса.

Вот простая репродукция, демонстрирующая проблему:

classa1.ps1:

#class A def 1
class A {
    [A] $next
}

testclassa.ps1:

. ./classa1.ps1
$aobj1 = new-object A
Write-Host "Current A definition GUID: $([A].guid)"

" " | out-file  -Append ./classa1.ps1
. ./classa1.ps1
$aobj2 = new-object A
Write-Host "New A definition GUID: $([A].guid)"

# throws conversion exception because the type definition of 
# $aobj1.next now differs from the current [A] definition
$aobj1.next = $aobj2
Exception setting "next": "Cannot convert the "A" value of type "A" to type "A"."  
At /home/veefu/src/throwaway/testclassa.ps1:13 char:1
+ $aobj1.next = $aobj2
+ ~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [], SetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenSetting

Кажется, система типов рассматривает две версии [A] как отдельные типы без преобразования между ними, несмотря на то, что фактическое определение [A] является идентичным.

Если ваш стиль обучения - мастурбация, то знакомство с методом .gettype() и выражением | format-list * пригодится вам. Они дают представление о типах и свойствах объектов, которые PS создает для вас. Непрозрачные ошибки, исходящие из кода, который должен «просто работать», часто выявляются путем проверки типа возвращаемого объекта. Я часто вспоминаю, что мои сценарии ожидали одного объекта и имели какое-то странное поведение или ошибку, где .gettype() уточняло, что моему сценарию фактически был задан набор объектов.

...