Question Comment créer un type Enum dynamiquement ?
- Arnaud Petitjean
- Auteur du sujet
- Hors Ligne
- Modérateur
il y a 3 ans 4 mois #30944
par Arnaud Petitjean
MVP PowerShell et créateur de ce magnifique forum
Auteur de 6 livres PowerShell aux éditions ENI
Fondateur de la société Start-Scripting
Besoin d'une formation PowerShell ?
Comment créer un type Enum dynamiquement ? a été créé par Arnaud Petitjean
Bonjour les amis !
Je cherche désepérement à créer un type Enum à partir de données présentes dans un fichier de configuration.
Imaginons que le fichier contiennent une liste de villes, par exemple :
Je souhaite lire ce fichier et créer dynamiquement un type enum pour m'en servir ensuite dans une classe en tant que type de l'un de mes membres.
Je pensais avoir trouvé une solution en utilisant les mécanismes de reflexion de .NET avec cette petite fonction :
Ainsi si j'appelle la fonction ainsi, par exemple :
Mais si j'essaie de créer une classe en utilisant ce type, cela ne fonctionne pas :
Du moins, si j'exécute ce script, j'obtient l'erreur suivante :
Le pire dans tout ça est que si je crée ma classe directement dans la console PS sans passer par un script, ça fonctionne.
Enfin, je ne suis pas sûr que ce soit une bonne idée de faire cela car la création du type Enum ne fonctionne carrément pas en PowerShell 7.
Merci d'avance pour votre éclairage !
Je cherche désepérement à créer un type Enum à partir de données présentes dans un fichier de configuration.
Imaginons que le fichier contiennent une liste de villes, par exemple :
Paris
Lyon
Bordeaux
Je souhaite lire ce fichier et créer dynamiquement un type enum pour m'en servir ensuite dans une classe en tant que type de l'un de mes membres.
Je pensais avoir trouvé une solution en utilisant les mécanismes de reflexion de .NET avec cette petite fonction :
Function New-Enum {
Param (
[String]$Name,
[String[]]$Values
)
$Domain = [AppDomain]::CurrentDomain
$DynAssembly = New-Object System.Reflection.AssemblyName('PrivilegeAssembly')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) # Only run in memory
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('PrivilegeModule', $False)
#endregion Module Builder
$global:EnumBuilder = $ModuleBuilder.DefineEnum($name, 'Public', [uint32])
$i = 0
$Values | ForEach-Object {
[void]$EnumBuilder.DefineLiteral($_, [uint32] $i++)
}
[void]$EnumBuilder.CreateType()
}
Ainsi si j'appelle la fonction ainsi, par exemple :
# Création du type Enum Location
PS > New-Enum -Name Location -Values 'paris','londres','milan'
# Je peux m'en servir de manière classique
PS > [location]::londres
londres
PS > [enum]::GetValues([Location])
paris
londres
milan
Mais si j'essaie de créer une classe en utilisant ce type, cela ne fonctionne pas :
Function New-Enum {
Param (
[String]$Name,
[String[]]$Values
)
$Domain = [AppDomain]::CurrentDomain
$DynAssembly = New-Object System.Reflection.AssemblyName('PrivilegeAssembly')
$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run) # Only run in memory
$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('PrivilegeModule', $False)
#endregion Module Builder
$global:EnumBuilder = $ModuleBuilder.DefineEnum($name, 'Public', [uint32])
$i = 0
$Values | ForEach-Object {
[void]$EnumBuilder.DefineLiteral($_, [uint32] $i++)
}
[void]$EnumBuilder.CreateType()
}
New-Enum -Name Location -Values 'paris','londres','milan'
class test {
[Location]$Emplacement
[Int]$Distance
}
Du moins, si j'exécute ce script, j'obtient l'erreur suivante :
Au caractère .\testEnumOnTheFly.ps1:24 : 7
+ [Location]$Emplacement
+ ~~~~~~~~
Type [Location] introuvable.
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : TypeNotFound
Le pire dans tout ça est que si je crée ma classe directement dans la console PS sans passer par un script, ça fonctionne.
Enfin, je ne suis pas sûr que ce soit une bonne idée de faire cela car la création du type Enum ne fonctionne carrément pas en PowerShell 7.
Merci d'avance pour votre éclairage !
MVP PowerShell et créateur de ce magnifique forum
Auteur de 6 livres PowerShell aux éditions ENI
Fondateur de la société Start-Scripting
Besoin d'une formation PowerShell ?
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Hors Ligne
- Modérateur
Réduire
Plus d'informations
- Messages : 6302
- Remerciements reçus 68
il y a 3 ans 4 mois #30945
par Laurent Dardenne
Tutoriels PowerShell
Réponse de Laurent Dardenne sur le sujet Comment créer un type Enum dynamiquement ?
Comme l'indique le bouton ceci sera une réponse rapide
Le problème que tu rencontres est dû au mécanisme de compilation ( exemple ), PS compile la classe AVANT tout le reste, ce qui implique que la classe Enum utilisée dans la déclaration n'existe pas encore.
En tout cas elle n'est pas créée en premier, ce qui est le cas avec la pluspart des langages compilé (qui schématiquement 'ordonne' les dépendances).
Dans ton cas, pour régler ce problème il me semble qu'il faille créer une dll dynamiquement sur disque (Add-Type le permet), ensuite s'appuyer sur le mécanisme de chargement d'un module ( une clé permet d'exécuter une script avant le chargement du module).
A tester.
Ce problème n'est pas aisée à résoudre il me semble, je regarde ça demain.
Le problème que tu rencontres est dû au mécanisme de compilation ( exemple ), PS compile la classe AVANT tout le reste, ce qui implique que la classe Enum utilisée dans la déclaration n'existe pas encore.
En tout cas elle n'est pas créée en premier, ce qui est le cas avec la pluspart des langages compilé (qui schématiquement 'ordonne' les dépendances).
Dans ton cas, pour régler ce problème il me semble qu'il faille créer une dll dynamiquement sur disque (Add-Type le permet), ensuite s'appuyer sur le mécanisme de chargement d'un module ( une clé permet d'exécuter une script avant le chargement du module).
A tester.
Ce problème n'est pas aisée à résoudre il me semble, je regarde ça demain.
Tutoriels PowerShell
Les utilisateur(s) suivant ont remercié: Arnaud Petitjean
Connexion ou Créer un compte pour participer à la conversation.
- Thomas PEREZ
- Hors Ligne
- Nouveau membre
Réduire
Plus d'informations
- Messages : 2
- Remerciements reçus 1
il y a 3 ans 4 mois #30948
par Thomas PEREZ
Réponse de Thomas PEREZ sur le sujet Comment créer un type Enum dynamiquement ?
Hello,
Il existe deux possibilités, la première via des fonctions et la deuxième en passant par une class importé dynamiquement.
Les deux méthodes sont utilisables sur PowerShell 5, 6, 7.
Méthode fonction :
Deuxième méthode avec une class :
Fichier PowerShell contenant la class.
Il existe deux possibilités, la première via des fonctions et la deuxième en passant par une class importé dynamiquement.
Les deux méthodes sont utilisables sur PowerShell 5, 6, 7.
Méthode fonction :
function Add-MyEnum
{
<#
.DESCRIPTION
Créé un enum.
#>
param
(
[String]$Name,
[Array]$values
)
Add-Type -TypeDefinition "
public enum $Name
{
$values
}
"
}
function Get-MyEnum
{
<#
.DESCRIPTION
Affiche une variable de type Enum.
#>
param (
[Service]$Name
)
$Name
}
# Ajout d'un nouveau Enum.
Add-MyEnum -Name Service -values @('Wsus, winserv')
# Appel d'une fonction contenant un paramètre de type Enum.
Get-MyEnum -Name 'winserv'
Deuxième méthode avec une class :
function Add-MyEnum
{
<#
.DESCRIPTION
Créé un enum.
#>
param
(
[String]$Name,
[Array]$values
)
Add-Type -TypeDefinition "
public enum $Name
{
$values
}
"
}
# Ajout d'un nouveau Enum.
Add-MyEnum -Name Service -values @('Wsus, winserv')
# Import d'une class dynamiquement.
$classModules = "using module monchemin\class.psm1"
$scriptBlock = [ScriptBlock]::Create($classModules)
. $scriptBlock
# Création d'une instance.
$test = [MyClass]@{MyEnum = 'Wsus' }
Fichier PowerShell contenant la class.
class MyClass
{
[Service]$MyEnum
MyClass ()
{
# $this.addEnum([String]$Name, [Array]$values)
}
}
Voila en ésperant que cela vous aide.
Bonne soirée.
Thomas.
Les utilisateur(s) suivant ont remercié: Arnaud Petitjean
Connexion ou Créer un compte pour participer à la conversation.
- Arnaud Petitjean
- Auteur du sujet
- Hors Ligne
- Modérateur
il y a 3 ans 4 mois #30951
par Arnaud Petitjean
MVP PowerShell et créateur de ce magnifique forum
Auteur de 6 livres PowerShell aux éditions ENI
Fondateur de la société Start-Scripting
Besoin d'une formation PowerShell ?
Réponse de Arnaud Petitjean sur le sujet Comment créer un type Enum dynamiquement ?
Hello Thomas !
Ca a l'air de correspondre en tous points à ce que je voulais faire.
Je vais tester ça.
Merci !
Ca a l'air de correspondre en tous points à ce que je voulais faire.
Je vais tester ça.
Merci !
MVP PowerShell et créateur de ce magnifique forum
Auteur de 6 livres PowerShell aux éditions ENI
Fondateur de la société Start-Scripting
Besoin d'une formation PowerShell ?
Connexion ou Créer un compte pour participer à la conversation.
- Arnaud Petitjean
- Auteur du sujet
- Hors Ligne
- Modérateur
il y a 3 ans 4 mois #30952
par Arnaud Petitjean
MVP PowerShell et créateur de ce magnifique forum
Auteur de 6 livres PowerShell aux éditions ENI
Fondateur de la société Start-Scripting
Besoin d'une formation PowerShell ?
Réponse de Arnaud Petitjean sur le sujet Comment créer un type Enum dynamiquement ?
Salut Laurent,
Thomas vient de poster une solution intéressante, qui je pense est la bonne.
Oui, on dirait bien que c'est le cas.Le problème que tu rencontres est dû au mécanisme de compilation ( exemple ), PS compile la classe AVANT tout le reste, ce qui implique que la classe Enum utilisée dans la déclaration n'existe pas encore.
Thomas vient de poster une solution intéressante, qui je pense est la bonne.
MVP PowerShell et créateur de ce magnifique forum
Auteur de 6 livres PowerShell aux éditions ENI
Fondateur de la société Start-Scripting
Besoin d'une formation PowerShell ?
Connexion ou Créer un compte pour participer à la conversation.
- Laurent Dardenne
- Hors Ligne
- Modérateur
Réduire
Plus d'informations
- Messages : 6302
- Remerciements reçus 68
il y a 3 ans 4 mois #30953
par Laurent Dardenne
Tutoriels PowerShell
Réponse de Laurent Dardenne sur le sujet Comment créer un type Enum dynamiquement ?
Salut,
>>qui je pense est la bonne.
Elle a qq contraintes en l'état ( portée de la classe et chemin codé en dur dans la clause using) mais donne une direction.
Il reste à la tester dans différent scénarios.
>>qui je pense est la bonne.
Elle a qq contraintes en l'état ( portée de la classe et chemin codé en dur dans la clause using) mais donne une direction.
Il reste à la tester dans différent scénarios.
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
Temps de génération de la page : 0.129 secondes
- Vous êtes ici :
- Accueil
- forum
- PowerShell
- Entraide pour les initiés
- Comment créer un type Enum dynamiquement ?