Search code examples
powershellpowershell-core

powershell Get-Member (MemberDefinition) to .Net MemberInfo


How to transition from PowerShell reflection to .Net reflection?

If I have MemberDefinition for a Method (i.e. '' | gm -Name Insert), how can get it attributes?


Solution

  • MemberDefinition is just a POCO with 4 data members, so nothing fancy can be done here: just use those string properties to resolve type/member.

    filter Resolve-NetType {
        [OutputType([System.Reflection.MemberInfo])] param()
        ([type]$_.TypeName).GetMember($_.Name)
    }
    
    '' | gm -Name ToString |
        Resolve-NetType |
        % { "$($_.GetType().Name) $($_.Name)($($_.GetParameters() | % { $_.CustomAttributes + $_.ParameterType + $_.Name}))" }
    
    # RuntimeMethodInfo ToString()
    # RuntimeMethodInfo ToString([System.Runtime.CompilerServices.NullableAttribute((Byte)2)] System.IFormatProvider provider)
    

    @mklement0 suggested to use PSMethod (late bound delegate in terms of C#), but it's actually more tricky to do anything with it beside Invoke, since there is no direct access to original type, but we can workaround it via reflection.

    $bindingFlagsAll=[System.Reflection.bindingflags]'IgnoreCase,Instance,Static,NonPublic,Public'
    
    function Get-Target {
        [OutputType([object])] param([System.Management.Automation.PSMemberInfo]$PSMember)
        [System.Management.Automation.PSMemberInfo].GetField('instance', $bindingFlagsAll).GetValue($PSMember)
    }
    

    So combined:

    filter Resolve-NetType {
        [OutputType([System.Reflection.MemberInfo])] param()
        # TODO: check $_.MemberType to filter out ETS members
        if ($_ -is [Microsoft.PowerShell.Commands.MemberDefinition])
        { ([type]$_.TypeName).GetMember($_.Name) }
        else
        { (Get-Target $_).GetType().GetMember($_.Name) }
    }
    
    (''.Chars, ($true | gm -Name ToString)) |
        Resolve-NetType |
        % { "$($_.GetType().Name) $($_.CustomAttributes) $($_.Name)" }
    
    # RuntimePropertyInfo  Chars
    # RuntimeMethodInfo [System.Runtime.CompilerServices.NullableContextAttribute((Byte)1)] ToString
    # RuntimeMethodInfo [System.Runtime.CompilerServices.NullableContextAttribute((Byte)1)] ToString