F#でコマンドレットを書いてる pt.5
krymtkts/pocof の話。ほぼ実装におけるメモ、壁打ち。
Out-ConsoleGridViewを見て hashtable
をフィルタできるのいいな~と思ったので、 hashtable
サポートを始めている。誰得な機能ではあれど、これがあると自分にとって利用の幅が広がる。
ProcessRecord
メソッドにおいて、 IDictionary
実装の場合のみ展開した要素を内部で保持するようにしてみた。一見して煩雑なので、なんかマシにしたい。 list
にして list
外すあたりがどーにも。
override __.ProcessRecord() =
- input <- List.append input <| List.ofArray __.InputObject
+ let entries: list<obj> =
+ List.ofArray __.InputObject
+ |> List.collect (fun (o: PSObject) ->
+ match o.BaseObject with
+ | :? IDictionary as dct ->
+ Seq.cast<DictionaryEntry> dct
+ |> Seq.cast<obj>
+ |> Seq.toList
+ | _ as o -> [ o ])
+
+ input <- List.append input entries
破壊的な操作ならすぐマシなのが思いつくが、ちょっと寝かせる。とはいえそっちでスッキリするならそっちがいいかな。
いや待て、ここまで書いて fold
の方がスッキリする気が...してきたので後でやってみる。
追記(2022-10-03)
要らんコードも取り除いてこうした。幾分マシかなあ。
override __.ProcessRecord() =
- input <- List.append input <| List.ofArray __.InputObject
+ input <-
+ List.ofArray __.InputObject
+ |> List.fold
+ (fun acc o ->
+ match o.BaseObject with
+ | :? IDictionary as dct ->
+ Seq.cast<obj> dct
+ |> Seq.fold (fun a d -> d :: a) acc
+ | _ as o -> o :: acc)
+ input
override __.EndProcessing() =
+ input <- List.rev input
この変更を加えることで hashtable
の各要素を扱えるようになるけど、依然フィルタした結果は得られない。
pocof
はいま内部的に各要素の ToString
メソッドの結果に対して LINQ のクエリをかけてる。
そのため DictionaryEntry
のような ToString
の結果が自身のクラスを示す文字列 System.Collections.DictionaryEntry
を返す場合、使い物にならない。
未実装のプロパティ指定可能にする機能があればまあ使えるので先にやるべきと考えるが、プロパティ未指定時の挙動が定義できてないといけない。
常時プロパティ指定なんてしないので、 ToString
に値が反映されないタイプのオブジェクトの場合に、デフォルトでフィルタ可能な挙動を定義する必要がある。あーこっちのが大事やわ。
やはり IDictionary
実装用に特別処理みたいなのを書いてあげないといけないかなーという気が若干してる。コイツ以外にも色々出てきたら面倒なので気が向かないけど、特別扱いなのはたしかにそうなので。
つづく