约束通用函数参数

时间:2012-09-27 09:05:11

标签: f#

我有这段代码

let inline ProcessExpendableADGroups (input : ('a * SPUser) seq) =
  input
  |> Seq.filter (fun (_, u : SPUser) -> u.IsDomainGroup = true)       
  |> Seq.filter (fun (_, u : SPUser) -> ADUtility.IsADGroupExpandable u.LoginName = true)      
  |> List.ofSeq
  |> List.iter( 
      fun ( li : 'a, u : SPUser) -> 
        let userList = ADUtility.GetUsers u.LoginName 
        if (Seq.length userList <= 500) then
          userList
          |> Seq.filter (fun l -> InfobarrierPolicy.IsUserInPolicy l "FW" = true) 
          |> Seq.iter (
              fun ln ->
                let x = ADUtility.GetNameAndEmail ln 
                let (email, name) = x.Value
                SPUtility.CopyRoleAssignment li u.LoginName ln email name
                li.Update()
              )
          SPUtility.RemoveRoleAssignment li u
      )      

list3 
|> List.iter (
    fun w -> 
      SPUtility.GetDirectAssignmentsforListItems w |> ProcessExpendableADGroups
      SPUtility.GetDirectAssignmentsforFolders w |> ProcessExpendableADGroups
      SPUtility.GetDirectAssignmentsforLists w |> ProcessExpendableADGroups
      SPUtility.GetDirectAssignmentsforWeb w |> ProcessExpendableADGroups
   )

这里GetDirectAssignmentsforListItems方法返回一个元组序列(SPListItem * SPUser) GetDirectAssignmentsforWeb返回一系列元组(SPWeb * SPUser)。

我需要将这个序列发送到一个函数,该函数对这些项进行非常类似的处理,但最后我必须在这些项上调用一个名为“Update”的方法。

我已经用Generic参数编写了一个方法但是当我在泛型参数上调用Update时遇到了问题。

我无法限制此参数来表示该参数必须具有名为Update的方法。

2 个答案:

答案 0 :(得分:3)

您可以使用成员约束和statically resolved type parameters来执行此操作。

let inline ProcessExpendableADGroups (input : (^a * SPUser) seq) = //'
  input
  |> Seq.filter (fun (_, u) -> u.IsDomainGroup && ADUtility.IsADGroupExpandable u.LoginName)       
  |> Seq.iter( 
      fun (li, u) -> 
        let userList = ADUtility.GetUsers u.LoginName 
        if (Seq.length userList <= 500) then
          userList
          |> Seq.filter (fun l -> InfobarrierPolicy.IsUserInPolicy l "FW") 
          |> Seq.iter (
              fun ln ->
                let x = ADUtility.GetNameAndEmail ln 
                let (email, name) = x.Value
                SPUtility.CopyRoleAssignment li u.LoginName ln email name
                (^a : (member Update : unit -> unit) li) //'
              )
          SPUtility.RemoveRoleAssignment li u
      ) 

还有一系列有关该主题here的有用文章。

我对上述功能做了一些改进:

  • 一系列Seq.filter可以折叠为一个Seq.filter= true始终是代码气味。
  • List.ofSeqList.iter可以由Seq.iter替换。当您使用Seq.iter时,无论如何都会评估延迟序列。
  • 不要编写冗余类型注释,例如li: 'au: SPUser。由于您使用管道并具有input的类型注释,因此类型检查器将能够推断出正确的类型。

答案 1 :(得分:2)

约束看起来就像这样(它不需要在方法中取消 - 就在你使用它的地方)

 (^a: ( member Update: unit-> unit )t))

这会在对象Update

上调用名为t的方法