Question Re:[Astuce]Créer un tableau en lecture seule

Plus d'informations
il y a 15 ans 10 mois - il y a 4 ans 4 mois #3414 par Laurent Dardenne
Ce code permet de créer un tableau en lecture seule à partir d'un tableau existant via l'appel de la méthode générique AsReadOnly .
Il utilise quelques méthodes du système de réflexion de .NET.
 #Déclare un tableau, il doit être typé
[Int32[]]$Tableau=1..10

 #La méthode AsReadOnly retourne un wrapper en lecture seule pour le tableau spécifié.
 #On recherche les informations de la méthode publique spécifiée.  
[System.Reflection.MethodInfo] $Methode = [System.Array].GetMethod(\"AsReadOnly\"«»)

 #Crée une méthode générique
 #On précise le même type que celui déclaré pour la variable $Tableau
$MethodeGenerique = $Methode.MakeGenericMethod([System.Int32])

 #Appel la méthode générique créée qui
 #renvoi une collection en lecture seule, du type :
 # [System.Collections.ObjectModel.ReadOnlyCollection``1[System.Int32]]
$TableauRO=$MethodeGenerique.Invoke($null,@(,$Tableau))

$Tableau[0]=10
$TableauRO[0]=10
 #Erreur : Unable to index into an object of type System.Collections.ObjectModel...
 #Resolve-Error
 
 #Les 2 tableaux pointent sur le même contenu
$Tableau
$TableauRO

 #Crée un tableau unique en lecture seule 
$TableauRO=$MethodeGenerique.Invoke($null,@(,$Tableau.Clone()))
$Tableau[0]=255
 #Les 2 tableaux ne pointent plus sur le même contenu
$Tableau
$TableauRO

 #Crée une variable en lecture seule sur un tableau unique en lecture seule
Set-Variable -name TReadOnly -value ($MethodeGenerique.Invoke($null,@(,$Tableau.Clone()))) -option Constant
$TReadOnly=$null
 #Erreur : Cannot overwrite variable TReadOnly because it is read-only or constant.
Ceci éliminera je pense quelques effets de bords dans les scripts :P<br><br>Message édité par: Laurent Dardenne, à: 15/12/08 13:25

Tutoriels PowerShell
Dernière édition: il y a 4 ans 4 mois par Laurent Dardenne. Raison: Balise code

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 7 ans 7 mois - il y a 4 ans 4 mois #23173 par Laurent Dardenne
MAJ:
Le code ci dessus ciblait la version 2 de PS, avec la 5.1 (à tester avec les précédentes versions) c'est tout de suite plus simple.
La méthode utilisée est une méthode générique
[System.Array]::AsReadOnly

#OverloadDefinitions
-------------------
#static System.Collections.ObjectModel.ReadOnlyCollection[T] AsReadOnly[T](T[] array)
Mais son usage est facilité :
$TableauRO=[System.Array]::AsReadOnly($Tableau)

$TableauRO[0]=99
#Unable to index into an object of type System.Collections.ObjectModel.ReadOnlyCollection`1[System.Int32].
La collection est bien générique :
$TableauRO.GetType().fullname
#System.Collections.ObjectModel.ReadOnlyCollection`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKey
Token=b77a5c561934e089]]
Il reste un piège avec la syntaxe PS :
 $TableauRO +=99
 $TableauRO
 $TableauRO.GetType().fullname
#System.Object[]
Ce qui est normale, car += itère la collection reçue ($TableauRO), puis y ajoute la valeur (99) et enfin renvoi un IEnumerable transformé en un tableau d'objet.

Tutoriels PowerShell
Dernière édition: il y a 4 ans 4 mois par Laurent Dardenne. Raison: Balise code

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 4 ans 4 mois - il y a 4 ans 4 mois #29842 par Laurent Dardenne
Un complément, protéger des collections dans un module :
#Protége la variable ET son contenu
New-Variable -Name ReadOnlyArray -Value ( [System.Array]::AsReadOnly(@('Un','Deux','trois') ) -Option Constant -Scope Script

#https://stackoverflow.com/questions/50030335/can-a-hash-be-made-readonly
$ReadOnlyDictionary = ([ordered]@{a=1}).AsReadOnly()
New-Variable -Name ReadOnlyDictionary -Value ( ([ordered]@{a=1 }).AsReadOnly() ) -Option Constant -Scope Script

#Protége la variable et son contenu et les élements contenu
$ReadOnlyDictionary = ([ordered]@{ Array = [Array]::AsReadOnly((1, 2, 3)) }).AsReadOnly()
La classe ReadOnlyDictionary peut aussi convenir mais nécessite plus de code (source : www.pstips.net/convertto-readonlydictionary.html ) et implique de la duplication de code ou l'ajout de dépendances.
Ceci étant dû aux conversions de type nécessaires car il n'existe pas de constructeur utilisant une simple hashtable :
function ConvertTo-ReadOnlyDictionary([System.Collections.Hashtable]$Hashtable=@{})
{
    $dict=New-Object 'System.Collections.Generic.Dictionary[[string],[object]]'
    $Hashtable.Keys.ForEach({$dict.Add($_,$Hashtable[$_])})
    return [System.Collections.ObjectModel.ReadOnlyDictionary[[string],[object]]]$dict
}

Tutoriels PowerShell
Dernière édition: il y a 4 ans 4 mois par Laurent Dardenne. Raison: Coquille

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.103 secondes
Propulsé par Kunena