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 循环和 if 条件,我的代码看起来非常必要。

而不是 for 循环,我想做一些类似 List.map 但是这些对象中的大多数,如 RoleDefinitionBindings 或 RoleAssignments 都返回给我不是列表、数组或序列的集合,所以我不得不编写循环。

当返回类型是自定义集合对象(如 SPRoleAssignmentCollection 和 SPRoleDefinitionBindingCollection)时,您能告诉我一种避免循环的方法吗?

4

1 回答 1

5

SPRoleDefinitionBindingCollection继承SPBaseCollectionwhich implements IEnumerable(但不是IEnumerable<T>, ie, seq<'T>)。您可以使用Seq.cast将 的实例IEnumerable转换为seq<'T>.

一旦你有了一个seq<'T>,你就可以使用 F#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 回答