カスタムプロバイダーを作ってみよう その3
前回の続きです。
今回はNew-Itemコマンドレットへの対応から始めます。
New-Itemコマンドレットへの対応
New-Itemコマンドレットに対応させるには、以下のメソッドをオーバーライドします。
- void NewItem(string path, string itemTypeName, object newItemValue)
FileSystemProviderでNew-Itemコマンドレットを使う場合を考えてみましょう。
PS c:\> New-Item 100.txt File -itemType File -value Hello
ファイル名とitemTypeに「File」か「Directory」、valueにファイルの内容を指定します。
これらのパラメータがNewItemメソッドのそれぞれの引数に対応する事は明白ですね。それでは実装してみましょう。
protected override void NewItem(string path, string itemTypeName, object newItemValue) { using(var fs = File.Create(path)) { base.WriteItemObject(new HogeFile { FileName = Path.GetFileName(path), Size = fs.Length }, path, false); } }
渡されたパスでファイルを作って、その情報をHogeFileオブジェクトとしてパイプラインに出力しています。
デバッグ実行して、動作をテストしてみましょう。
PS Hoge:\> New-Item 400.txt ファイル名 ファイルサイズ ---------- -------------- 400.txt 0
例えば、以下のように-BufferSizeというパラメータで数値を指定すると、
PS Hoge:\>New-Item 400.txt -BufferSize 128 ファイル名 ファイルサイズ ---------- -------------- 400.txt 128
こういった新しいパラメータを定義するためのDynamicParametersという仕組みがプロバイダーには用意されています。
例えばNew-Itemコマンドレットに新しいパラメータを定義するには、NewItemDynamicParametersというメソッドをオーバーライドします。
このメソッドのシグネチャを見てみると、
- object NewItemDynamicParameters(string path, string itemTypeName, object newItemValue)
となっていますが、引数はNewItemメソッドと同じで返り値がobject型になっています。このメソッドはNewItemメソッドが呼び出される前に必ず呼び出されるようになっています。
では、このメソッドの返り値として何を返せばいいのでしょうか?
答えは以下のようなパラメータをプロパティとして持つプレーンなクラスを定義して、そのインスタンスを返します。
NewItemParameters.cs
[Serializable] [DebuggerStepThrough] public class NewItemParameters { [Parameter] public int BufferSize { get; set; } }
パラメータとして定義するプロパティにはParameter属性でマークをしておきます。
では、このクラスのインスタンスを返すようにNewItemDynamicParametersメソッドを実装しておきます。
protected override object NewItemDynamicParameters(string path, string itemTypeName, object newItemValue) { return new NewItemParameters(); }
protected override void NewItem(string path, string itemTypeName, object newItemValue) { var niParams = base.DynamicParameters as NewItemParameters; var bufferSize = niParams != null ? niParams.BufferSize : 0; using(var fs = File.Create(path, bufferSize)) { fs.Write(new byte[bufferSize], 0, bufferSize); base.WriteItemObject(new HogeFile { FileName = Path.GetFileName(path), Size = fs.Length }, path, false); } }
動的パラメータはDynamicParametersプロパティで取得できます。動的パラメータが定義されていれば、BufferSizeを取得して、そのサイズのファイルを作成しています。
これでデバッグ実行すると前述のように動作するはずです。
このようにして既存のコマンドレットに新しいパラメータを追加する仕組みがプロバイダーには用意されています。おもしろいですね!!
ファイル作成ができるようになったので、その逆のファイルの削除もできるようにしておきましょう。
Remove-Itemコマンドレットへの対応
Remove-Itemコマンドレットに対応させるには、以下のメソッドをオーバーライドします。
- void RemoveItem(string path, bool recurse)
- bool HasChildItems(string path)
RemoveItemメソッドはそのままですが、HasChildItemsメソッドはどういう役割でしょうか?
このメソッドはアイテムを削除する時にそのアイテムに子アイテムがあるかどうかを問い合わせます。このメソッドがfalseを返せばアイテムは削除されますが、trueを返せばRemove-Itemコマンドレットで-forceパラメータが指定された場合のみ削除されます。
これはすごく単純なのでさっさと実装します。
protected override bool HasChildItems(string path) { return false; } protected override void RemoveItem(string path, bool recurse) { File.Delete(path); }
これだけです。
デバッグ実行して、以下のコマンドを実行するとファイルが削除されるはずです。
PS Hoge:\> Remove-Item 400.txt