Question [Module] Gestion de classes immutables

Plus d'informations
il y a 6 ans 3 mois #17938 par Laurent Dardenne
Voici un module de gestion de classes immutable , ou plus simplement des collections en lecture seule.
L'objectif du module ImmutableBcl est de créer dynamiquement des wrappers (fonctions powershell) à partir de déclaration, ceci afin de simplifier la création de ces classes.
On peut aussi utiliser directement le module PSGenericMethods qui propose une fonction d'appel de méthode générique ce que ne sait pas faire Powershell.

Quelques exemples (présent dans l'archive jointe) :
[code:1]
#requires -Version 3.0
cd G:\ps\Immutable\
Import-Module \"$pwd\PSGenericMethods.psm1\" -ErrorAction Stop
$m=Ipmo \"$pwd\Immutablebcl.psd1\" -pass

#Par défaut créer les wrappers des méthodes suivantes :
Get-DefaultMethod
Get-Command New-Immutable*|Select-Object Name

#On peut paramètrer la création de fonctions 'wrapper'
# $MesMethodes=@(
# @{
# Type='System.Collections.Immutable.ImmutableSortedDictionary'
# MethodName='CreateBuilder'
# GenericType=@('String','Int')
# }
# )
# $m=Ipmo \"$pwd\Immutablebcl.psd1\" -ArgumentList $MesMethodes -pass
# $m.exportedcommands

#http://msdn.microsoft.com/en-us/library/dn467194%28v=vs.110%29.aspx
#Appel une méthode statique d'une classe générique,
# ici la clé et sa valeur doivent être de type System.string
#On crée une hashtable triée immutable vide
$Immutable=[System.Collections.Immutable.ImmutableSortedDictionary[string,string]]::Empty
$Immutable
#Liste vide, pas d'affichage par défaut

$Immutable.GetType().FullName
$Immutable|gm

$Immutable.Add('Clé','Valeur')
$Immutable
#Liste vide, car ici Add() n'ajoute pas un nouvel élément,
#mais construit une seconde instance du même type que $Immutable
$NewImmutable=$Immutable.Add('Clé','Valeur')
$Immutable #vide
$NewImmutable #un élément


#Appel, via une fonction du module PSGenericMethods ( github.com/dlwyatt/PSGenericMethods ),
#la méthode générique ImmutableSortedDictionary.Create<string,String>
#On crée une hashtable triée immutable vide
$ISD=Invoke-GenericMethod -Type System.Collections.Immutable.ImmutableSortedDictionary -MethodName Create -GenericType String,String
$ISD.GetType()

#Crée un builder autorisant l'ajout, la hashtable n'est pas immutable :
# ImmutableSortedDictionary.CreateBuilder<string,String>
#Construction via splatting
$params=@{
Type='System.Collections.Immutable.ImmutableSortedDictionary'
MethodName='CreateBuilder'
GenericType=@('String','String')
}
$ISD=Invoke-GenericMethod @Params
#Conversion implicite d'un entier en string
$ISD.Add('a',10)
#La hastable est sensible à la casse
$ISD.Add('A',10)
$ISD
#La clé existe -> Erreur
$ISD.Add('A',11)

$params=@{
Type='System.Collections.Immutable.ImmutableSortedDictionary'
MethodName='CreateBuilder'
GenericType=@('String','String')
#Crée une hashtable immutable insensible à la casse
ArgumentList =([System.StringComparer]::InvariantCultureIgnoreCase)
}
$ISD=Invoke-GenericMethod @Params
#Builder est une classe imbriquée, cf .présence du caractère '+' dans le nom de type :
# System.Collections.Immutable.ImmutableSortedDictionary`2+Builder[[System.String, ...
$ISD.GetType().Fullname

$ISD.Add('a',10)
#La hastable est sensible à la casse
#La clé existe -> Erreur
$ISD.Add('A',11)
$ISD.Add('B',11)
$ISD.Add('C',11)
$ISD


$H=$ISD.ToImmutable()
#$H est désormais une hastable immutable
$H
#renvoi une nouvelle instance
$H.Add('D',12)
$H
#La clé existe -> Erreur
$H.Add('A',12)

#Affiche les fonctions exportées par le module Immutablebcl
$m.exportedcommands

#Les fonctions New-Immutable* sont des wrappers
${function:New-ImmutableSortedDictionary_Create_String_Object}
#Norme de nommage :
# New-Immutable SortedDictionary = Nom court du TYPE
# _Create_ = Nom de la méthode générique
# String_Object = Nom des types passés à la méthode générique

Get-Help New-ImmutableSortedDictionary_Create_String_Object -full
#Ces méthodes déclarent le paramètre -Argumentlist.
#Il permet d'appeler une des surcharges de la méthode générique encapsulée
#La ligne '1 : System.Collections.Generic.IComparer`1[TKey] keyComparer'
#précise le type du paramètre et son nom en C#
#Sous PS on passe autant d'objets qu'il y a de paramètres

#Appel une fonction construisant une hashtable immutable à partir d'un hashtable 'basic'
$H=@{}
$H.Add(\"txt\", \"notepad.exe\"«»);
$H.Add(\"bmp\", \"paint.exe\"«»);
$H.Add(\"dib\", \"paint.exe\"«»);
$H.Add(\"rtf\", \"wordpad.exe\"«»);

#Converti la hashtable en un Dictionnaire générique(on utilise les mêmes déclaration de type, ici String,String)
#puis on crée une hastable immutable
$NewImmutable=New-ImmutableSortedDictionary_CreateRange_String_String (ConvertTo-Dictionary $h string,string)

#Modification -> erreur
# La méthode spécifiée n'est pas prise en charge.
# + CategoryInfo : OperationStopped: (:«») [], NotSupportedException
# + FullyQualifiedErrorId : System.NotSupportedException
$NewImmutable.bmp='test'
#Ajout -> erreur identique
$NewImmutable.aze='test'

#fonctionne, mais renvoi une autre ImmutableSortedDictionary égale à $Immutable
#mais sans l'elément 'bmp' s'il existe
$NewImmutable.remove('bmp')
#Sensible à la casse
#l'élément n'est pas supprimé
$NewImmutable.remove('BMP')

#On passe en parmètre un tableau d'objets,
#le premier est un objet de comparaison de chaînes insensible à la casse,
#le second est un dictionnaire générique crée à parit d'une hashtable 'basic'.
#
#Les parenthèses sont nécessaire autour du premier objet, sinon PS passe une string...
$NewImmutable=New-ImmutableSortedDictionary_CreateRange_String_String ([System.StringComparer]::InvariantCultureIgnoreCase),(ConvertTo-Dictionary $H string,string)
#Insensible à la casse
#l'élément supprimé
$NewImmutable.remove('BMP')


#Crée une fonction dans la portée globale
$VerbosePreference='continue'
$F=New-FunctionInvokeGenericMethod -Type 'System.Collections.Immutable.ImmutableSortedDictionary' -MethodName 'CreateBuilder' -GenericType @('Int','Object')
$F
${function:New-ImmutableSortedDictionary_CreateBuilder_Int32_Object}

#Génére une hashtable contenant les paramètres utilisés par les cmdlets Set-Item/New-Item
#Appel en dot source
&{
$F=. New-FunctionInvokeGenericMethod -Type 'System.Collections.Immutable.ImmutableSortedDictionary' -MethodName 'CreateBuilder' -GenericType @('Int','String')
$F
#Crée une fonction dans la portée courante.
#Pour ce dernier cas, la conception des modules oblige cette approche
New-Item @F -force > $null
}
#La fonction New-ImmutableSortedDictionary_CreateBuilder_Int32_String
#n'existe pas dans la portée courante
Get-Command New-ImmutableSortedDictionary_CreateBuilder*|Select-Object Name

#Une fois les méthode globale crées,
# on peut supprimer le module
Remove-Module Immutablebcl

#Il reste une seule fonction :
# New-ImmutableSortedDictionary_CreateBuilder_Int32_Object
Get-Command New-Immutable*|Select-Object Name

#Cette fonction reste opérationnelle, car ses prérequis sont tjr chargés.
New-ImmutableSortedDictionary_CreateBuilder_Int32_Object
$Builder=New-ImmutableSortedDictionary_CreateBuilder_Int32_Object
$Builder|gm

# Les prérequis
Get-Module PSGenericMethods
[Appdomain]::CurrentDomain.GetAssemblies()|
where-object Location -match 'Immutable.Net40|ReadOnlyCollectionsInterfaces'
[/code:1]

La pièce jointe ImmutableBcl.zip est absente ou indisponible

<br><br>Message édité par: Laurent Dardenne, à: 18/08/14 19:43

Tutoriels PowerShell
Pièces jointes :

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

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