Indirectly Invoking Methods Via Variablenames

PowerShell Team

PSMDTAG:FAQ: Can I specify a methodname using a variable? e.g. $x.$y()

PSMDTAG:FAQ: Why do I get METHOD metadata when I specify a method without providing parentheses?

One of the great things about Windows PowerShell is that it is a latebound language which allows you to do all sorts of incredibly powerful operations.  Consider the following code which defines a function to display the properties of an object.  The names of the properties come from a file passed into the function:

PS> function test ($obj, $file) {
>> foreach ($prop in cat $file) {“{0,-12} : {1}” -f $prop, $obj.$prop}
>> }
>>

PS> cat properties.txt
Name
ID

PS> test (get-process notepad) properties.txt
Name         : notepad
ID           : 456

PS> cat properties2.txt
Name
WS
NPM
Handles

PS> test (get-process notepad) properties2.txt
Name         : notepad
WS           : 7483392
NPM          : 4520
Handles      : 50

This works because you can specify $Obj.$Prop  where $prop contains the name of the property you want to see.

So how about Methods?  Lets see how that works:

PS> $s=”This is a TEST”
PS> $method=”ToUpper”
PS> $s.$method()
Unexpected token ‘(‘ in expression or statement.
At line:1 char:12
+ $s.$method() <<<<

It turns out the the parser does not handle this situation. 

But now try this:

PS> $s=”This is a TEST”
PS> $s.ToUpper()
THIS IS A TEST
PS> $s.ToUpper

MemberType          : Method
OverloadDefinitions : {System.String ToUpper(), System.String ToUpper(Cultu
                      reInfo culture)}
TypeNameOfValue     : System.Management.Automation.PSMethod
Value               : System.String ToUpper(), System.String ToUpper(Cultur
                      eInfo culture)
Name                : ToUpper
IsInstance          : True

What is happening is that if you specify a METHOD with parens, we call it.  If you specify a method without parens, we return the metadata for that method.  This can be a tad non-plussing at first but it turns out to be very useful at times.  In particular, it allows you to do this:

PS> $s=”This is a TEST”
PS> $s.ToUpper.Invoke()
THIS IS A TEST
PS> foreach ($method in “ToUpper”,”ToLower”,”GetType”) {$s.$method.Invoke()}

THIS IS A TEST
this is a test

IsPublic IsSerial Name                                     BaseType
——– ——– —-                                     ——–
True     True     String                                   System.Object

Enjoy!

 

Jeffrey Snover [MSFT]
Windows PowerShell/Aspen Architect
Visit the Windows PowerShell Team blog at:   
http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

PSMDTAG:INTERNAL: Indirectly invoking methods via variable Names

PSMDTAG:LANGUAGE: Parser does not accept directly support variable substitution for method names

0 comments

Discussion is closed.

Feedback usabilla icon