2014-03-28 118 views
0

我們有一個要求,用戶無權訪問的Sharepoint列表的項目必須仍然在前端對用戶可見,並且可以選擇「請求訪問「,如果有必要。爲此,我們有一個Web服務,首先獲取列表中的所有項目,然後下一個僅獲取用戶有權訪問的項目。Sharepoint - 獲取兩個SPListItemCollection之間的差異

// Get all the items in list 
SPUser superUser = SPContext.Current.Web.AllUsers[@"SHAREPOINT\SYSTEM"]; 
SPUserToken superToken = superUser.UserToken; 
SPList superList; 
using (SPSite site = new SPSite(SPContext.Current.Web.Url, superToken)) 
{ 
    using (SPWeb elevatedWeb = site.OpenWeb()) 
    { 
     superList = elevatedWeb.Lists.TryGetList(listname); 
    } 
} 
SPListItemCollection superListItems = superList.GetItems(camlQuery); 


// Get items in list accessible to current user 
SPUser regularUser = SPContext.Current.Web.CurrentUser; 
SPUserToken regularToken = regularUser.UserToken; 
SPList regularList; 
using (SPSite site = new SPSite(SPContext.Current.Web.Url, regularToken)) 
{ 
    using (SPWeb regularWeb = site.OpenWeb()) 
    { 
     regularList = regularWeb.Lists.TryGetList(listname); 
    } 
} 
SPListItemCollection regularListItems = regularList.GetItems(camlQuery); 

接下來,需要計算兩個list-item-collections之間的差異。這應該已經是很簡單的,如果這是可能的:

// Now make a list of the items that the current user DOES NOT HAVE ACCESS TO 
SPListItemCollection noAccessListItems; 
foreach (SPListItem superListItem in superListItems) 
{ 
    if(!regularListItems.Contains(superListItem)) // Fails here 
    { 
     noAccessListItems.Add(superListItem); 
    } 
} 

唯一的問題是,SPListItemCollection不支持.Contains()方法。

獲得兩個list-item-collection對象的區別的最好方法是什麼?

回答

1

您可以使用Cast來使用所有IEnumerable LINQ方法,如Contains()。 使用try-catch這不是太漂亮的解決方案,恕我直言。 你可以做一個簡單的一行:

var noAccessListItems = regularListItems.Cast<SPListItem>().Where(x => !superListItems.Cast<SPListItem>().Select(y => y.ID).Contains(x.ID)); 

或者這樣:

var noAccessListItems = regularListItems.Cast<SPListItem>().Except(superListItems.Cast<SPListItem>()); 

但在這種情況下,你必須爲SPListItem定義比較器。

UPDATE1:

要定義你需要實現從的IEqualityComparer繼承像這類比較器:

class SPListItemEqualityComparer : IEqualityComparer<SPListItem> 
{ 
    public bool Equals(SPListItem i1, SPListItem i2) 
    { 
     return i1.ID == i2.ID; 
    } 

    public int GetHashCode(SPListItem item) 
    { 
     int hCode = item.ID; 
     return hCode.GetHashCode(); 
    } 
} 

然後你需要添加這個類作爲第二個參數的實例在Except方法:

var noAccessListItems = superListItems.Except(regularListItems, new SPListItemEqualityComparer()); 
+0

謝謝!這似乎是一個更好的解決方案。您可以詳細說明LINQ解決方案與try-catch的性能嗎?此外,如果您展示瞭如何爲SPListItem編寫比較器,那將是一件好事。 – SNag

+0

@SNag,這不是關於性能(我不認爲它真的很不一樣)。這是關於代碼可讀性的。更新了我的答案以包含比較器代碼段。 –

+0

再次感謝!如果它是關於可讀性的話,那麼IMO的LINQ比try-catch更難閱讀。比較器解決方案雖然是最好的。我給了你一個投票並接受你的答案。 :) – SNag

0

好的。得到它的工作。這工作:

// Now make a list of the items that the current user DOES NOT HAVE ACCESS TO 
SPListItemCollection noAccessListItems; 
foreach (SPListItem superListItem in superListItems) 
{ 
    try 
    { 
     regularListItems.GetItemById(superListItem.ID); 
    } 
    catch(ArgumentException ae) 
    { 
     noAccessListItems.Add(superListItem); 
    } 
}