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?
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