1. ホーム
  2. powershell

[解決済み] PowerShell でスクリプトが使用するカスタムタイプを作成するにはどうすればよいですか?

2023-02-06 05:30:20

質問

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でこのようなことは可能でしょうか、あるいは推奨されるでしょうか?

どのように解決するのですか?

PowerShell 3 より前のバージョン

PowerShell の Extensible Type System では、もともと、パラメータで行ったような方法でテストできる具象型を作ることができませんでした。そのテストが必要ないのであれば、上記の他の方法で問題ないでしょう。

もしあなたが、例のスクリプトのように、キャストしたり型チェックをしたりできる実際の型が欲しいなら...それは はできません。 C# や VB.net で書いてコンパイルしないとできない。PowerShell 2では、"Add-Type"コマンドを使用して、非常に簡単にそれを行うことができます。

add-type @"
public struct contact {
   public string First;
   public string Last;
   public string Phone;
}
"@

歴史的メモ : PowerShell 1ではもっと大変でした。手動でCodeDomを使用しなければならず、非常に古い関数である 新しい構造 スクリプトがPoshCode.orgにあるので、それを使うといいでしょう。あなたの例は、次のようになります。

New-Struct Contact @{
    First=[string];
    Last=[string];
    Phone=[string];
}

使用方法 Add-Type または New-Struct を使用すると、実際にクラスをテストすることができます。 param([Contact]$contact) で実際にテストし、新しいものを作ることができます。 $contact = new-object Contact を使って新しいものを作るなど...

PowerShell 3では

キャストできる "real" クラスが必要ない場合は、以下のような Add-Member の方法を使用する必要はありません。 Steven や他の人が実証している を使用する必要はありません。

PowerShell 2以降では、New-Objectの-Propertyパラメータを使用することができます。

$Contact = New-Object PSObject -Property @{ First=""; Last=""; Phone="" }

そして、PowerShell 3 では、このように PSCustomObject アクセラレータを使用して TypeName を追加できるようになりました。

[PSCustomObject]@{
    PSTypeName = "Contact"
    First = $First
    Last = $Last
    Phone = $Phone
}

まだオブジェクトが1つしか取得できていない状態なので、そのオブジェクトに対応するように New-Contact 関数を使用して、すべてのオブジェクトが同じように出力されることを確認する必要があります。しかし、パラメータを PSTypeName 属性で装飾することで、パラメータがこれらの型のいずれかであることを簡単に確認できるようになりました。

function PrintContact
{
    param( [PSTypeName("Contact")]$contact )
    "Customer Name is " + $contact.First + " " + $contact.Last
    "Customer Phone is " + $contact.Phone 
}

PowerShell 5では

PowerShell 5 ではすべてが変わり、ついに classenum を型を定義するための言語キーワードとして使用します。 struct はありませんが、それはそれでOKです)。

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"
}