今回も前回に続き PowerShell v5 をコアとする Windows Management Framework 5.0 Preview September 2014 (v5.0) の機能詳細を触りつつ、何が変わるのかお伝えできればと思います。
- Develop with classes in Windows PowerShell
ついにクラスが PowerShell で操作できます。やったー!
- 追記 : PowerShel v5 がリリースされました
- 過去の記事はこちら
目次
できること
簡単にいうと、いわゆる object-oriented なスタイルでの記述です。例を挙げると、
- Enumの宣言
- Class構文
- Properties
- Methods
- Inheritance (継承)
などなど。
これを使って、
- DSC Resource の記述
- 独自型をPowerShel Script だけで規定、利用
- 規定した型のデバッグがPowerShellで買おうに
- 例外処理も、正しく適切なレベルで行えるように
できないこと
現状まだできないことは多くあります。
- Property が public しかなく、ReadOnly などはできない
- Get-DSCResourceでは、Class構文で書かれたリソースを検知できない
- DSC エンジンキャッシュが、PowerShellスクリプトモジュールに向けて作りこまれているため、DebugModeを有効にする必要があります
- New-Object でのクラス生成ができず、Static Method である
[ClassName]::New()
を使う必要がある
カスタムタイプ
規定できるものをさくっと見てみましょう。
Class Keyword
.NET Framework に基づく新しいクラスを規定します。
メンバーはパブリックですが、パブリックな範囲は 「モジュールスコープ」に限定されています。
現段階では、 スクリプトやモジュールで規定したMyClass
クラスを、モジュール/スクリプトの外部から[MyClass]
のような形式で検知することはできません。
つまり、文字列からクラスを検知できないため、New-Object
を使うことができません。
構文
Class MyClass { }
Enum Keyword と列挙
もし July Preview を使っていた人がいたら破壊的変更になります。 Enumのデリミタが,
ではなく、改行
になりました。
ついにきました。Enumです。PowerShell では、Enumが相当活躍するので、独自に規定できるのは大事です。
従来は、Class同様に C# で書いて、Add-Type で読み込む必要がありました。
たとえば、Valentia ではこういった型を持っています。
これが、Enumキーワードを使えばこんな感じで規定できます。
素晴らしいです。もう Tyr{}Catch{} も不要です。AppDomainで苦しまずにすみます。
構文
Enum MyEnum { }
制限
現状は、Enumerator Value はEnumキーワード実行時に決まっている必要があります。
つまり、何かのコマンドの結果とすることはできません。
たとえば、こうはできます。
Enum Colour { Blue = [int]::MaxValue }
が、こうはできません。
Enum Colour2 { Yellow = (Get-childItem).Count }
このような警告がでます。
算術結果はサポートしているのでこういうのはありです。
Enum SomeEnum { Max = 42 } Enum OtherEnum { Max = [SomeEnum]::Max + 1 }
Import-DscResouce
これまでもキーワードでしたが、正しく Dynamic Keyword となりました。
PowerShell は、このキーワードを使って、Rootモジュールを走査して [DSCResource()] 属性をもったクラスを検知します。
Properies
ModuleInfo に ImplementingAssembly
フィールドが追加されました。
これは、スクリプトモジュール内のクラスや、C# Cmdletで書かれた バイナリモジュールのためのです。なので、 ModuleType が Manufest、つまり psd1 だとでません。
ImplementingAssembly フィールドをリフレクションすると、どんなリソースがモジュールに含まれるかわかります。つまり、PowerShell や他の言語からどんなリソースが存在しているか調べれるということです。
まさに、chef のため(?) と思えそうな機能ですね!
Initializing
フィールドの初期化として
[int] = 5;
などとかくこともできます。
Static
Static がサポートされているので、こうかけます。
Static [int] = 5;
やったね。
すべてPublic
現状はPublicのみです(えー
Classの スコープが Lexical Scope なので、クラス外部からの影響やクラス外部への影響はありません。
関数 Function{}
や ScirptBlock {}
で悩まされたあの問題が完全回避できるのはうれしいですね。
しかし、すべて Publicかぁ。
Constructor
Constructor も利用可能です。
C# 同様にクラスと同名である必要があります。また、overload可能です。
Static Constructor も利用可能で、Static Property は Static Constructor の前に初期化されます。
同様に、インスタンスプロパティは、non-Static Constructor の前に初期化されます。
制限
現状は、C#にあるようなConstructor を別の Constructor から呼ぶシンタックスはないので次のような記述はできません。
: this()
インスタンス生成
クラスのインスタンス生成は、従来の New-Object
がまだ使えないのでスタティックメソッドを利用します。
$MyClass = [MyClass]::new()
これで、$MyClass でもにょれます。
Constructor の例を見てみましょう。
this がないのは、現状の制限です。
Method
PowerShell の Class構文における Method は、ScriptBlock つまり匿名コンストラクタを使っています。
ScriptBlock の End節のみ使っているのが特徴です。型付けできるのでいい感じです。
属性
Class には、特定の属性が用意されています。
- DscResource
- DscResourceKey
- DscResourceMandatory
です。いずれも DSC Resource として組む場合のキーになるものです。
スコープ
先ほど説明したとおり、Lexical Scope です。
リリースノートのサンプルはこんな感じですね。
まとめ
どうでしょうか。少しはとっつきやすくなったでしょうか。
初めは Def とかあって、Ruby... え。でしたが、リリースノートからは C# を意識しているようです。
Cmdlet を書け?はい。でも、まぁうれしいと思います。