1

F#を使用してSharePoint 2010オブジェクトを操作しようとしています(実験と同じように)。

だから私はこのコードを書きます

let getSPDomainUsers (spWeb : SPWeb) =
seq {
  for r in spWeb.RoleAssignments do
    match r.Member with
    | :? SPUser as user ->        
      for b in r.RoleDefinitionBindings do
        if (user.IsDomainGroup) then yield (spWeb.Url.ToLower(), user, b.Name.ToLower())
    | :? SPGroup as group ->
      for u in group.Users do
        for b in r.RoleDefinitionBindings do
          if (u.IsDomainGroup) then yield (spWeb.Url.ToLower(), u, b.Name.ToLower())
    | _ -> ()
} 

ただし、これらすべてのforループと条件がある場合、私のコードは非常に必須に見えます。

forループの代わりにList.mapのようなことをしたいのですが、RoleDefinitionBindingsやRoleAssignmentsのようなこれらのオブジェクトのほとんどは、リスト、配列、シーケンスではないコレクションを返すので、ループを作成する必要があります。

戻り型がSPRoleAssignmentCollectionやSPRoleDefinitionBindingCollectionなどのカスタムコレクションオブジェクトである場合に、ループを回避する方法を教えてください。

4

1 に答える 1

5

SPRoleDefinitionBindingCollectionSPBaseCollection実装するものを継承しますIEnumerable(ただし、は継承しませんIEnumerable<T>seq<'T>Seq.castのインスタンスをに変換するIEnumerableために使用できますseq<'T>

を取得したら、F#モジュールseq<'T>で通常の関数を使用できます。Seq

これがあなたのコードのクリーンアップされたバージョンです。SharePointを持っていないので、コンパイル/テストできません。IEnumerableカスタムコレクションタイプをにパイプする前に、明示的にキャストする必要がある場合がありますSeq.cast

let userInfo (user : SPUser) =
    user.RoleDefinitionBindings
    |> Seq.cast<SPRoleDefinition>
    |> Seq.choose (fun b ->
        if user.IsDomainGroup then
            Some (spWeb.Url.ToLower(), user, b.Name.ToLower())
        else None)

let getSPDomainUsers (spWeb : SPWeb) =
    spWeb.RoleAssignments
    |> Seq.cast<SPRoleAssignment>
    |> Seq.collect (fun r ->
        match r.Member with
        | :? SPUser as user ->
            userInfo user
        | :? SPGroup as group ->
            Seq.collect userInfo group.Users
        | _ ->
            Seq.empty)
于 2012-08-21T17:44:10.567 に答える