2016-04-22 6 views
3

Ich versuche die PowerShell-Klassen zu verwenden, was sehr praktisch ist, um zusammengehörige Daten zu gruppieren Verhalten. Das vereinfachte Szenario: Ein PS-Skript, das die Klasse definiert, und ein anderes Skript, das diese Klasse verwendet.PowerShell 5 und Klassen - Der "X" -Wert des Typs "X" kann nicht in "X" konvertiert werden

Common.ps1

class X 
{ 
    [string] $A 
} 

Script1.ps1

. $PSScriptRoot\Common.ps1 

[X] $v = New-Object X 

Alles ist gut - kann man Script1.ps1 beliebig viele Male ohne Probleme laufen - bis Sie make beliebig chang e in Common.ps1. Ihnen wird der folgende Fehler angezeigt.

 
Cannot convert the "X" value of type "X" to type "X". 
At D:\temp\PSIssue\Script1.ps1:3 char:1 
+ [X] $v = New-Object X 
+ ~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : MetadataError: (:) [], ArgumentTransformationMetadataException 
    + FullyQualifiedErrorId : RuntimeException 

Vorstellbar jede Änderung (auch wenn Sie nur Leerzeichen hinzugefügt) in PS-Datei zwingt seine erneute Kompilierung, so dass Typ X anders wird als X sie verwendet werden - temporäre Behälteranordnung (ganz gleich geändert wurde Problem leicht reproduzierbar in .NET - Typen sind identisch, solange "Vollqualifizierte Assembly-Namen" gleich sind. Änderung in Script1.ps1 lässt Dinge wieder normal funktionieren.

Gibt es eine Möglichkeit, solche Probleme zu überwinden?

+3

Ja nicht zwei derselben Runspace/session/Appdomain in, verwenden verschiedene Implementierungen von 'X' (dh . 'exit' powershell, re-launch) –

+0

@ MathiasR.Jessen, gibt es eine Möglichkeit in PowerShell ISE alles neu zu laden/neu zu kompilieren? Ich schließe es gerade komplett und öffne es von Grund auf neu ... –

+0

Wenn Sie den Fehler ignorieren und das Skript nur ein zweites Mal ausführen, bekomme ich den Fehler nicht und laufe erneut, dann bekomme ich die aktualisierte Klasse. Sollte für feine Tests in Ordnung sein. – Matt

Antwort

2

Ich konnte Ihr Problem replizieren und beheben. Ähnlich verhält es sich, wenn Sie eine Klasse in einem Bereich definieren und versuchen, eine andere Klasse im selben Bereich zu definieren. Die Klassendefinition wird in der PowerShell-Sitzung beibehalten. In Script1.ps1 müssen Sie den Code so ändern, dass die zu typisierende Variable nicht explizit deklariert wird. Verwenden Sie einfach, wie unten zu nicht stark verwenden Typing und lassen Sie Powershell den Typ bestimmen und zuweisen dynamisch:

. $PSScriptRoot\Common.ps1 

$v = New-Object X 

Jetzt sollten Sie in der Lage sein, die Definition der Klasse X in Common.ps1 so oft wie Sie ändern wollen, ohne zu schließen und neu zu laden.

Das obige Beispiel verwendet „Schwache Typisierung“ Du mehr über diese und andere Details hier lesen: Variable Types and Strongly Typing

+1

Wenn dies wahr ist, können Sie auch einfach 'Remove-Variable v' verwenden. – Matt

+0

Das funktioniert nicht mit Strongly typisierte Variable, da PowerShell die Variable immer noch an ihre ältere Definition bindet. Ich versuchte es, um sicher zu sein, und beobachtete dasselbe Ergebnis wie die ursprüngliche Frage. Um es zu lösen, müssen Sie eine schwach typisierte Variable verwenden, wie ich im Beispiel gezeigt habe. –

+0

@AmanSharma, danke für den Vorschlag, es funktioniert definitiv, aber ich finde explizite Typen sehr praktisch in der Entwicklung von Skripten - es entweder klarer und erlaubt IDE, bessere Arbeit in Auto-Vervollständigung zu tun ... –