Comment puis-je conditionnellement ajouter une classe avec des Add-Type -TypeDefinition si elle n'est pas déjà ajouté?
Considérer le PowerShell suivant extrait de:
$csharpString = @"
using System;
public sealed class MyClass
{
public MyClass() { }
public override string ToString() {
return "This is my class. There are many others " +
"like it, but this one is mine.";
}
}
"@
Add-Type -TypeDefinition $csharpString;
$myObject = New-Object MyClass
Write-Host $myObject.ToString();
Si je le lance plusieurs fois dans le même domaine d'application (par exemple, exécuter le script à deux reprises dans powershell.exe ou powershell_ise.exe) j'obtiens l'erreur suivante:
Add-Type : Cannot add type. The type name 'MyClass' already exists.
At line:13 char:1
+ Add-Type -TypeDefinition $csharpString;
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (MyClass:String) [Add-Type],
Exception
+ FullyQualifiedErrorId :
TYPE_ALREADY_EXISTS,Microsoft.PowerShell.Commands.AddTypeCommand
Comment puis-je placer l'appel Ajoutez-Type -TypeDefinition de sorte que son seul appelé une seule fois?
Vous devez vous connecter pour publier un commentaire.
Cette technique fonctionne bien pour moi:
En interne, le PSTypeName appels de classe de la LanguagePrimitives.ConvertStringToType() méthode qui gère le levage lourd. Il met en cache la recherche de chaîne de caractères en cas de succès, de nouvelles recherches sont plus rapides.
Je n'ai pas confirmé si des exceptions sont générées à l'interne, comme l'a mentionné x0n et Justin D.
En fait, rien de tout cela est nécessaire. Ajoutez-Type maintient un cache de code que vous lui soumettre, avec le type résultant. Si vous appelez Ajouter de Type deux fois avec le même code, alors il ne sera pas pris la peine de compiler le code et il suffit de retourner le type de la dernière fois.
Vous pouvez le vérifier en exécutant simplement un Add-Type appel deux fois dans une rangée.
La raison pour laquelle vous avez le message d'erreur dans l'exemple ci-dessus, c'est que vous avez modifié le code entre les appels à Ajouter de Type. Si la solution ci-dessus fait l'erreur d'aller loin dans cette situation, cela signifie également que vous travaillez avec une ancienne définition du type qui n'est probablement pas le jeu de la façon dont vous pensez qu'elle est.
Remove-Type
; voir cette réponse pour plus sur la meilleure façon de contourner cette limitation: stackoverflow.com/questions/3369662/...Il y a une plus belle façon de le faire
sans encourir le coût des exceptions:mise à jour: bien, apparemment powershell signaux à l'interne, à l'exception de toute façon. Il a la mauvaise habitude de le faire. L'interprète utilise SEH de signal avec la
break
etcontinue
mots-clés, par exemple."MyCladdss" -as [type]
- je obtenir(1e04.2424): CLR exception - code e0434352 (first chance)
. Donc, je ne suis pas explicitement de faire un try/catch dans mon code, mais le CLR est.Automation.PSInvalidCastException
Message: Ne peut pas convertir le "MyCladdss" valeur "type de Système.Chaîne" pour "type de Système.Tapez". Il n'y a pas de InnerException. Peut-être que je suis ignorant de détail de Windows Internals, mais ne serait pas tout CLR invoquer l'exception de la structuration de la Gestionnaire d'Exception (SEH) et appeler un PROCESSEUR exception, et, par conséquent, ont les mêmes problèmes de performance? Fait quelque chose, je suis pas de faire le particulier à l'exception de la matière?La façon la plus simple pour ce faire est un bloc try/catch. Vous avez deux possibilités pour cela:
try { [MyClass] | Out-Null } catch { Add-Type -TypeDefinition $csharpString; }
try { Add-Type -TypeDefinition $csharpString; } catch {}
De cette façon, aucune exception n'est levée, c'est juste un peu lent base sur le nombre d'assemblages chargés de: