Как создать пользовательский тип в PowerShell для использования моими сценариями?
Я хотел бы иметь возможность определять и использовать пользовательский тип в некоторых из моих сценариев PowerShell. Например, давайте представим, что у меня была потребность в объекте, который имел следующую структуру:
Contact
{
string First
string Last
string Phone
}
Как бы мне создать это, чтобы я мог использовать его в функции, как показано ниже:
function PrintContact
{
param( [Contact]$contact )
"Customer Name is " + $contact.First + " " + $contact.Last
"Customer Phone is " + $contact.Phone
}
возможно ли что-то подобное или даже рекомендуется в PowerShell?
7 ответов:
создание пользовательских типов можно выполнить в PowerShell.
Кирк Мунро на самом деле имеет два больших сообщения, которые подробно описывают процесс.книги Windows PowerShell в действии от Manning также есть пример кода для создания доменного языка для создания пользовательских типов. Книга превосходна всем вокруг, так что я действительно рекомендую его.
Если вы просто ищете быстрый способ сделать выше, вы можете создать функцию для создания пользовательского объекта, как
function New-Person() { param ($FirstName, $LastName, $Phone) $person = new-object PSObject $person | add-member -type NoteProperty -Name First -Value $FirstName $person | add-member -type NoteProperty -Name Last -Value $LastName $person | add-member -type NoteProperty -Name Phone -Value $Phone return $person }
до PowerShell 3
расширяемая система типов PowerShell изначально не позволяла создавать конкретные типы, которые вы можете протестировать, как это было сделано в вашем параметре. Если вам не нужен этот тест, вы прекрасны с любым из упомянутых выше методов.
если вам нужен фактический тип, который вы можете привести или ввести-проверьте, как в вашем примере сценария ... это не может можно сделать без записи в C# или VB.net и компиляция. в PowerShell 2, Вы можете использовать команду "Add-Type", чтобы сделать это довольно просто:
add-type @" public struct contact { public string First; public string Last; public string Phone; } "@
Историческая Справка: в PowerShell 1 это было еще сложнее. Вы должны были вручную использовать CodeDom, есть очень старая функция new-struct скрипт включен PoshCode.org и это поможет. Ваш пример становится:
New-Struct Contact @{ First=[string]; Last=[string]; Phone=[string]; }
используя
Add-Type
илиNew-Struct
позволит вам на деле проверить классparam([Contact]$contact)
и сделать новые с помощью$contact = new-object Contact
и так на...В PowerShell 3
Если вам не нужен "реальный" класс, который вы можете привести, вам не нужно использовать метод Add-Member, который Стивен и другие продемонстрировали выше.
начиная с PowerShell 2 Вы можете использовать параметр-Property для New-Object:
$Contact = New-Object PSObject -Property @{ First=""; Last=""; Phone="" }
и в PowerShell 3, мы получили возможность использовать
PSCustomObject
ускоритель для добавления имени типа:[PSCustomObject]@{ PSTypeName = "Contact" First = $First Last = $Last Phone = $Phone }
вы все еще только один объект, так что вы должны сделать
New-Contact
функции, чтобы убедиться, что каждый объект выходит то же самое, но теперь вы можете легко проверить параметр "является" одним из тех типов, украшая параметр с :function PrintContact { param( [PSTypeName("Contact")]$contact ) "Customer Name is " + $contact.First + " " + $contact.Last "Customer Phone is " + $contact.Phone }
В PowerShell 5
в PowerShell 5 все меняется, и мы, наконец, получил
class
иenum
как ключевые слова языка для определения типов (нетstruct
но это нормально):class Contact { # Optionally, add attributes to prevent invalid values [ValidateNotNullOrEmpty()][string]$First [ValidateNotNullOrEmpty()][string]$Last [ValidateNotNullOrEmpty()][string]$Phone # optionally, have a constructor to # force properties to be set: Contact($First, $Last, $Phone) { $this.First = $First $this.Last = $Last $this.Phone = $Phone } }
мы также получили новый способ создавать объекты без использования
New-Object
:[Contact]::new()
-- на самом деле, если вы сохранили свой класс простым и не определяете конструктор, вы можете создавать объекты путем приведения хэш-таблицы (хотя без конструктора не было бы никакого способа принудительно установить все свойства):class Contact { # Optionally, add attributes to prevent invalid values [ValidateNotNullOrEmpty()][string]$First [ValidateNotNullOrEmpty()][string]$Last [ValidateNotNullOrEmpty()][string]$Phone } $C = [Contact]@{ First = "Joel" Last = "Bennett" }
ответ Стивена Муравски велик, однако мне нравится более короткий (или, скорее, просто более аккуратный select-object вместо использования синтаксиса add-member):
function New-Person() { param ($FirstName, $LastName, $Phone) $person = new-object PSObject | select-object First, Last, Phone $person.First = $FirstName $person.Last = $LastName $person.Phone = $Phone return $person }
существует концепция PSObject и Add-Member, которые вы могли бы использовать.
$contact = New-Object PSObject $contact | Add-Member -memberType NoteProperty -name "First" -value "John" $contact | Add-Member -memberType NoteProperty -name "Last" -value "Doe" $contact | Add-Member -memberType NoteProperty -name "Phone" -value "123-4567"
этого мероприятия, как:
[8] » $contact First Last Phone ----- ---- ----- John Doe 123-4567
другой альтернативой (о которой я знаю) является определение типа В C#/VB.NET и загрузка этой сборки в PowerShell для непосредственного использования.
это поведение определенно рекомендуется, потому что оно позволяет другим сценариям или разделам вашего сценария работать с фактическим объектом.
удивлен, что никто не упомянул этот простой вариант (vs 3 или более поздней версии) для создания пользовательских объектов:
[PSCustomObject]@{ First = $First Last = $Last Phone = $Phone }
тип будет PSCustomObject, а не фактический пользовательский тип. Но это, вероятно, самый простой способ создать пользовательский объект.
вот жесткий путь для создания пользовательских типов и хранения их в коллекции.
$Collection = @() $Object = New-Object -TypeName PSObject $Object.PsObject.TypeNames.Add('MyCustomType.Contact.Detail') Add-Member -InputObject $Object -memberType NoteProperty -name "First" -value "John" Add-Member -InputObject $Object -memberType NoteProperty -name "Last" -value "Doe" Add-Member -InputObject $Object -memberType NoteProperty -name "Phone" -value "123-4567" $Collection += $Object $Object = New-Object -TypeName PSObject $Object.PsObject.TypeNames.Add('MyCustomType.Contact.Detail') Add-Member -InputObject $Object -memberType NoteProperty -name "First" -value "Jeanne" Add-Member -InputObject $Object -memberType NoteProperty -name "Last" -value "Doe" Add-Member -InputObject $Object -memberType NoteProperty -name "Phone" -value "765-4321" $Collection += $Object Write-Ouput -InputObject $Collection