Setting multiple properties at once - equivalent of VB's With statement to provide an implied object context

瘦欲@ 提交于 2020-07-18 07:42:48

问题


For sake the of learning only.

Let's say I have a variable, in this example a textbox, how could I set many properties at once without typing the variable name over and over.

I've attempted some stuff my self, one of them work for some odd reason.

This example works. Break is used to shorten the loop.

 $Textbox | % {
    $_.Text = "Hello World"
    $_.Background = "Black"
    $_.Foreground = "Green"
    Break
 }

These two examples do not work and are here just to see what I've attempted.

This was with and without "$_."s and instead of a "." I've used "=" and "+=", none of which worked.

 $Textbox.@{
    Text = "Hello World"
    Background = "Black"
    Foreground = "Green"
 }

 $Textbox.({
    $_.Text = "Hello World"
    $_.Background = "Black"
    $_.Foreground = "Green"
 })

There may be a easier way to do, I haven't come across anything on google.


回答1:


What you're looking for is a language construct such as VB[Script]'s With statement, which allows you to set an implied context for "object-less" property references (such as .Text) inside a block.

There is no such construct in PowerShell.

Your 1st attempt is the closest emulation in PowerShell, albeit at the expense of performance (though that may not matter): in a pipeline, automatic variable $_ allows for a concise reference to the input object at hand.

Important: Do not use break inside a pipeline: it won't just exit the pipeline, it will exit any enclosing loop and, in the absence of one, the enclosing script. Use return instead.

That said, in the case at hand, with only a single input object, return is not needed.


As for your other attempts:

  • Syntax @{...} is only used for hashtable literals. Trying to use this syntax as a property name causes a syntax error.

  • Syntax (...) evaluates any single command / expression enclosed; {...} defines a script block.

    • A script block that isn't actually executed (which would require &), when used in a string context - such as a property name here, evaluates to its literal contents between { and }, i.e., a multiline string that clearly does not represent the name of an existing property of $TextBox, so the overall result is $null.

    • Note that a script run in the appropriate strict mode - with Set-StrictMode -Version 2 or higher - would have flagged the above attempt to access a non-existent property as an error.
      By contrast, an attempt to assign to a non-existent property always generates an error.


Note, however, that PowerShell offers convenient multi-property initialization in the context of constructing objects, which in PowerShell you can frequently also achieve with casts, via hashtable initializers.

# Cast a hashtable with property name/value pairs to
# [System.Windows.Forms.TextBox], which implicitly constructs
# an instance with the specified property values:
$TextBox = [System.Windows.Forms.TextBox] @{
  Text = "Hello World"
  Location = [Point]::new(10, 50)
}

The caveat is that the availability of this technique depends on whether the target type has a parameter-less constructor - see this answer for details.




回答2:


In case you maintain dictionaries (hashtables) of properties for other purposes as well, you can write a simple function that applies the data to an object:

function Set-Properties(
    [parameter(ValueFromPipeline)] $inputObject,
    [hashtable] $properties,
    [switch] $passThru
) {
    process {
        Add-Member -InputObject $inputObject -NotePropertyMembers $properties -force
        if ([bool]$passThru) { $inputObject }
    }
}

Usage:

Set-Properties $Textbox @{
    Text = "Hello World"
    Background = "Black"
    Foreground = "Green"
}

$Textbox1, $Textbox2 | Set-Properties -properties @{
    Text = "Hello World"
    Background = "Black"
    Foreground = "Green"
} -passThru | ForEach {
    # do something
}


来源:https://stackoverflow.com/questions/42378637/setting-multiple-properties-at-once-equivalent-of-vbs-with-statement-to-provi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!