2012-09-27 50 views
1

我有此代碼約束通用功能參數

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的方法。

回答

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的類型註釋,因此類型檢查器將能夠推斷出正確的類型。
+0

爲什麼我們要聲明成員Update:unit - > unit兩次?一次在功能標題中,然後再次在調用時? –

+1

我太過分了。我更新了答案,刪除了它,並添加了解釋「a」和「^ a」之間區別的鏈接。 – pad

2

約束只是看起來像這樣(它並不需要在方法decleration - 只在您使用它)

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

這將調用該對象上調用Update方法t

+0

有點困惑。泛型參數應該是'a或^ a? –

+1

對於這種內嵌約束,您需要使用'^ a'。通常,雖然你需要''a' –