Вы можете значительно сократить "шум" и повторяемость в вашем коде с помощью следующих методов, которые не требуют наследования / расширения типа [1] :
Используйте New-Object
с параметром -Property
, которому вы можете передать хеш-таблицу свойств, что позволяет избежать необходимости сначала создавать переменную, а затемприсваивать свойства индивидуально:
$amuletLabelValueDmg = New-Object Windows.Forms.Label -Property @{
Location = New-Object Drawing.Point 10, 20
Size = New-Object Drawing.Size 60, 20
Text = 'Value'
}
$groupBoxAmulet.Controls.Add($amuletLabelValueDmg)
Примечание:
Я еще более сократил код, исключив префикс System.
в именах типов, который обычно необязательно в PowerShell (за исключением вызовов Add-Type
, Update-TypeData
и Update-FormatData
и операторов using assembly
и using namespace
).
В стороне: Обратите внимание, как я изменил синтаксис некоторых вызовов New-Object
, например Drawing.Size (60,20) to
New-Object Drawing.Size 60,20 . The no-whitespace
(60,20) syntax should be avoided, because it is based on mistaking the syntax for a _method call_, which it isn't:
60, 20 is an array _argument_ that is bound to the (implied)
-ArgumentList` параметр;аргументы передаются без скобок, разделенных пробелами.
В PSv5 + вы можете сократить это с помощью cast и static ::new()
method для литералов типов вместо New-Object
, а также с оператором using namespace
для сокращения имен типов :
# Load the System.Windows.Forms assembly
# which implicitly loads System.Drawing too.
using assembly System.Windows.Forms
# Declare implied namespaces, so that types from
# the loaded assemblies can be referred to by mere name
# (e.g., 'Form' instead of 'System.Windows.Forms')
using namespace System.Windows.Forms
using namespace System.Drawing
$amuletLabelValueDmg = [Label] @{
Location = [Point]::new(10, 20)
Size = [Size]::new(60, 20)
Text = 'Value'
}
$groupBoxAmulet.Controls.Add($amuletLabelValueDmg)
В любом случае вы можете создать простых функций-оболочек (здесь для краткости используется PSv5 +; функцию можно и нужно сделать гораздо более надежной):
function New-Label {
param(
[int[]] $Location,
[int[]] $Size,
[string] $Text
)
# Create and output a new label control
[Label] @{
Location = [Point]::new($Location[0], $Location[1])
Size = [Size]::new($Size[0], $Size[1])
Text = $Text
}
}
$amuletLabelValueDmg = New-Label 10,20 60,20 Value
Наконец, вы можетеуменьшить потребность во вспомогательных переменных путем передачи литерала массива в метод Controls.AddRange()
элемента управления контейнера (предполагается наличие функции New-Label
, определенной выше):
$groupBoxAmulet.Controls.AddRange(@(
New-Label 10,20 60,20 Value
New-Label 10,40 60,20 Health
New-Label 10,60 60,20 Resistance
))
[1] Пока ялично я думаю, что это того не стоит, если вы действительно хотите сделать это с расширениями наследования / типов , вам придется прикрепить свой собственный код создания элемента управления к объекту типа элемента (например, [System.Windows.Forms.Label]
) вместо индивидуального экземпляров (обратите внимание, что, аналогично, Update-TypeData -TypeName System.Windows.Forms.Label ...
сделает только новые определенные элементы доступными только для уже существующих экземпляров ).
# Define a Create() method for the label *type* that acts as a factory
# method and outputs a new label *instance*.
# Note that the method becomes an *instance method* of the *type* object.
Add-Member -Force -InputObject ([System.Windows.Forms.Label]) -MemberType ScriptMethod `
-Name Create -Value { #`#
param(
[int[]] $Location,
[int[]] $Size,
[string] $Text
)
New-Object $this.FullName -Property @{
Location = New-Object Drawing.Point $Location[0], $Location[1]
Size = New-Object Drawing.Size $Size[0], $Size[1]
Text = $Text
}
}
# Call the type's new instance method with the desired arguments.
$amuletLabelValueDmg = [System.Windows.Forms.Label].Create((10,20), (60,20), 'Value')