Question [Fonction] Construction de signatures d'interface

Plus d'informations
il y a 8 ans 6 mois #20756 par Laurent Dardenne
La version 5 permet d'implémenter des interfaces, voici une fonction qui construit les signatures des membres d'une interface.
les membres supportés sont les propriétés et les méthodes, pas les event :
[code:1]
Function Show-InterfaceSignature{
param (
[Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)]
[ValidateNotNull()]
[string] $TypeName
)

process {
[System.Type]$Type=$null
if (-not [System.Management.Automation.LanguagePrimitives]::TryConvertTo($TypeName,[Type],[ref] $Type))
{
$Exception=New-Object System.ArgumentException('Le type est inconnu.','TypeName')
Write-Error -Exception $Exception
return
}
if (-not $Type.isInterface)
{
Write-Warning \"Le type $Type n'est pas une interface.\"
return
}
$Members=$Type.GetMembers()
$isContainsEvent=@($Members|Where {$_.membertype -eq 'Event'}|Select -First 1).Count -ne 0

if ((-not $isContainsEvent))
{
#Pour les propriétées d'interfaces,
#les méthodes suffisent à l'implémentation de la propriété
#todo setter R/O
$Members=$Members|Group-object MemberType -AsHashTable -AsString
$body=\"`tthrow 'Not implemented'\"
#Recherche les propriété indexées
Foreach($PropertiesGroup in $Members.Property|Group Name){
Foreach($Property in $PropertiesGroup.Group){
$Indexers=$Property.GetIndexParameters()
$isIndexers=$Indexers.Count -gt 0
if ($isIndexers)
{
Write-Output \"#TODO [System.Reflection.DefaultMember('$($Property.Name)')]\"
#todo une classe VB.Net peut avoir + indexers ?
#http://blogs.msdn.com/b/jaybaz_ms/archive/2004/07/21/189981.aspx
Break
}
}
}
Foreach($Method in $Members.Method){
$Ofs=\",`r`n\"
$Parameters=\"$(
Foreach ($Parameter in $Method.GetParameters())
{
Write-Output ('[{0}] ${1}' -f $Parameter.ParameterType,$Parameter.Name)
}
)\"

Write-Output (\"[{0}] {1}($Parameters){{`r`n$Body`r`n}}`r`n\" -f $Method.ReturnType,$Method.Name)
}
}
Else
{
Write-Error \"L’interface [$Type] contient un ou des événement. Son implémentation est impossible sous Powershell.\"
}
}
} #Show-InterfaceSignature
[/code:1]
Un exemple, on utilise un paramètre de type string la fonction le convertit dans le type correspondant :
[code:1]
'System.IConvertible',
'System.ComponentModel.INotifyPropertyChanged', #Event. Add-type -AssemblyName System.ComponentModel
'SystemInt32',
'System.Int32'| Show-InterfaceSignature
#
# [System.TypeCode] GetTypeCode(){
# throw 'Not implemented'
# }
#
# [System.Boolean] ToBoolean([System.IFormatProvider] $provider){
# throw 'Not implemented'
# }
#
# ...
#
# [System.Object] ToType([System.Type] $conversionType,
# [System.IFormatProvider] $provider){
# throw 'Not implemented'
# }
#
# Show-InterfaceSignature : L'interface [System.ComponentModel.INotifyPropertyChanged] contient un ou des événement.
# Son implémentation est impossible sous Powershell.
#
# Show-InterfaceSignature : Le type est inconnu.
# Nom du paramètre : TypeName
#
# AVERTISSEMENT : Le type int n'est pas une interface.
[/code:1]
Il reste la génération des interfaces générique à implémenter et qq tests à effectuer... à suivre<br><br>Message édité par: Laurent Dardenne, à: 29/09/15 20:32

Tutoriels PowerShell

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

Plus d'informations
il y a 8 ans 5 mois #20769 par Laurent Dardenne
Ajout de la gestion d'un indexeur présent sur une interface, car il est possible d'en implémenter avec les classes Powershell v5 :
[code:1]
[System.Reflection.DefaultMember(\&quot;Tab\&quot;«»)]
class MyClass
{
Hidden [int[]] $Tab = (new-object int[] 100)
[int] get_Tab([int]$i) { return $this.Tab[$i]}
[void] set_Tab([int]$i,[int] $Value) { $this.Tab[$i]=$Value}
}
$o=[MyClass]::New()
$o.Tab=0..99
$o[3]
[/code:1]
Pour l'interface suivante :
[code:1]
public interface IIndexer2
{

int Item
{
get;
set;
}
//Item est le nom de propriété par défaut d'un indexeur
//Si Item existe déjà, on modifie le nom de propriété de l'indexer
[System.Runtime.CompilerServices.IndexerName(\&quot;MyItem\&quot;«»)]
string this[int index]
{
get;
set;
}
}
[/code:1]
L'appel suivant :
[code:1]
'Test.IIndexer2'| Show-InterfaceSignature
[/code:1]
Génère ce squelette des méthodes Powershell à implémenter :
[code:1]
#TODO [System.Reflection.DefaultMember('MyItem')]
[System.Int32] get_Item(){
throw 'Not implemented'
}

[System.Void] set_Item([System.Int32] $value){
throw 'Not implemented'
}

[System.String] get_MyItem([System.Int32] $index){
throw 'Not implemented'
}

[System.Void] set_MyItem([System.Int32] $index,
[System.String] $value){
throw 'Not implemented'
}[/code:1]

Message édité par: Laurent Dardenne, à: 29/09/15 20:47<br><br>Message édité par: Laurent Dardenne, à: 29/09/15 20:48

Tutoriels PowerShell

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

Plus d'informations
il y a 7 ans 3 semaines #23252 par Laurent Dardenne
Nouvelle version, elle utilise le verbe Get et réécriture autour d'un StringBuilder.
Offre une meilleure génération des propriétés :
[code:1]
Function Get-InterfaceSignature{
#Affiche les signatures des membres d'une interface
param (
[Parameter(Position=0, Mandatory=$true, ValueFromPipeline=$true)]
[ValidateNotNull()]
[string] $TypeName
)

process {
Write-debug \&quot;TypeName : $TypeName\&quot;

[System.Type]$Type=$null
if (-not [System.Management.Automation.LanguagePrimitives]::TryConvertTo($TypeName,[Type],[ref] $Type))
{
$Exception=New-Object System.ArgumentException('Unknown type.','TypeName')
Write-Error -Exception $Exception
return
}
if (-not $Type.isInterface)
{
Write-Warning \&quot;The type $Type is not an interface.\&quot;
return
}
$Members=$Type.GetMembers()
$isContainsEvent=@($Members|Where-Object {$_.MemberType -eq 'Event'}|Select-Object -First 1).Count -ne 0

if ((-not $isContainsEvent))
{
$Members=$Members|Group-object MemberType -AsHashTable -AsString
$Script=New-Object System.Text.StringBuilder \&quot;`r`n# $TypeName`r`n\&quot;

#Recherche les propriétés indexées
$PropertiesGroup=$Members.Property|Group Name
Foreach ($Property in $PropertiesGroup.Group){
$Indexers=$Property.GetIndexParameters()
if ($Indexers.Count -gt 0)
{
#Note: une classe VB.Net peut avoir + indexers via des propriétés
# test 'System.Collections.IList'
$Script.AppendLine(@\&quot;
#Todo Decorate the class definition with the following line :
[System.Reflection.DefaultMember('$($Property.Name)')]
\&quot;@ ) &gt;$null
Break
}
}

Foreach ($Property in $Members.Property){
Write-debug \&quot;Add property : $($Property.Name)\&quot;
$Script.AppendLine( (\&quot;`t[{0}] `${1}\&quot; -F $Property.PropertyType, $Property.Name) ) &gt;$null
}

Foreach($Method in $Members.Method){
$oldOfs,$Ofs=$ofs,\&quot;,`r`n\&quot;
Write-Debug \&quot;Method name : $($Method.Name)\&quot;
if ($Method.Name -match '^(?&lt;Accessor&gt;G|S)et_(?&lt;Name&gt;.*$)')
{
if ($Matches.Accessor -eq 'G')
{ $Body=\&quot;`t return `$this.{0}\&quot; -F $Matches.Name }
else
{ $Body=\&quot;`t `$this.{0} = `${1}\&quot; -F $Matches.Name,($Method.GetParameters())[0].Name }
}
else
{ $Body=\&quot;`t throw 'Not implemented'\&quot; }

$Parameters= Foreach ($Parameter in $Method.GetParameters())
{
Write-debug \&quot;Add parameter method : $($Parameter.Name)\&quot;
\&quot;`t`t[{0}] `${1}\&quot; -f $Parameter.ParameterType,$Parameter.Name
}
if ($Parameters.Count -ne 0)
{
$Script.AppendLine( (\&quot;`r`n`t[{0}] {1}(`r`n$Parameters){{`r`n$Body`r`n`t}}`r`n\&quot; -f $Method.ReturnType,$Method.Name) ) &gt;$null
}
else
{ $Script.AppendLine( (\&quot;`r`n`t[{0}] {1}(){{`r`n$Body`r`n`t}}`r`n\&quot; -f $Method.ReturnType,$Method.Name) ) &gt;$null }
}
Write-Output $Script.ToString()
}
Else
{ Write-Error \&quot;The interface [$Type] contains one or more events. Its implementation is impossible with Powershell.\&quot; }
}
} #Get-InterfaceSignature
[/code:1]
Un exemple :
[code:1]
Add-Type -TypeDefinition @'
public interface Interface2 {
bool Property { get;set; }
bool Method();
}
'@

Get-InterfaceSignature Interface2
## Interface2
# [System.Boolean] $Property
#
# [System.Boolean] get_Property(){
# return $this.Property
# }
#
#
# [System.Void] set_Property(
# [System.Boolean] $value){
# $this.Property = $value
# }
#
#
# [System.Boolean] Method(){
# throw 'Not implemented'
# }
[/code:1]<br><br>Message édité par: Laurent Dardenne, à: 3/03/17 13:47

Tutoriels PowerShell

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

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