Strongly Typed SharePoint List Collections By Template Type

When working with numerous types of lists positioned in a particular web, site, or higher storage medium, it becomes beneficial to build strongly typed SPList collections representing your data source instruments into a class level field for comfortable access and on-demand querying. Refining the approach slightly further, it is even more advantageous to extract template type selection into a paradigm that can be easily manipulated from general interface controls for filter of type if required.

To accomplish this, firstly we are going to build two new classes. One class will contain the static methods, and the other will represent an enumeration that we can switch on that containing the list template types I want to make available.

Firstly, the enumeration:

[csharp]
public enum IncludedListTypes
{
All,
DocumentLibrary,
Events
}
[/csharp]

The above could observably have a lot more values (it probably should), for like Survey or Announcement lists, but are not included for brevity.

Next, we are going to build two global fields, one providing the class level collection backing field and the other to represent the IncludedListTypes value.

[csharp]
private IncludedListsTypes _type = IncludedListsTypes.All;
private List _masterCollection = new List();
[/csharp]

Moving right along, we are going to build the HydrateListCollectionByTemplate method which will use the previously built enumeration. This will take a ICollection and an SPList object as a parameter. Again, to handle further template types follows an identical paradigm, but not included for brevity.

[csharp]
private void HydrateListCollectionByTemplate(ICollection listsList, SPList list)
{
switch (_type)
{
case IncludedListsTypes.All:
listsList.Add(list);
break;
case IncludedListsTypes.DocumentLibrary:
if (Equals(list.BaseTemplate, SPListTemplateType.DocumentLibrary))
{
listsList.Add(list);
}
break;
case IncludedListsTypes.Events:
if (Equals(list.BaseTemplate, SPListTemplateType.Events))
{
listsList.Add(list);
}
break;
}
}
[/csharp]
Calling this method is pretty straight forward, and naturally is used mostly with recursion. Consider the below, which just gets an SPListCollection from the current context, and hydrates the class level SPList typed collection. Pretty straight forward.

[csharp]
public void PushListsToMasterCollection()
{
foreach (SPList curList in SPContext.Current.Web.Lists)
{
HydrateListCollectionByTemplate(_masterCollection, curList);
}
}
[/csharp]

Share

Best Practice: Don’t Iterate SPListItems for IQueryable Support

I saw this during a code review today. Essentially, to support a LINQ query into a SPListItemCollection, there was an iteration that converted the SPListItemCollection to a typed List collection, the secondary collection subsequently being queried through LINQ. While SPListItemCollection implements IEnumerable it is challenging to use when converting the instance to IQueryable because it will fall back on IEnumerable specification since it simplements IEnumerable, not IQueryable.

The method in question looked like this:

[csharp]
public static List ConvertToTypedList(SPListItemCollection collection)
{
List items = new List();
foreach (SPListItem item in collection)
{
items.Add(item);
}
return items;
}
[/csharp]

That iteration IMHO is entirely too expensive for performance reasons because of dual collection builds, and it’s just plain ugly. For each query run, execute collection generation of an already existing collection? No thanks! :)

Instead, just use Cast(), it’s much cleaner and this is the exact situation it is used for. Replicating the intent of the above iteration, I can simply express in the domain terms (via method chaining) the LINQ query (which you can obviously modify with whatever query you like).

[csharp]
var results = SPContext.Current.Web.Lists[“Some List”].Items.Cast().Select(item => item);
[/csharp]
For example, to using a where clause for a specific title:
[csharp]
var results = SPContext.Current.Web.Lists[“Some List”].Items.Cast().Where(item => item[SPBuiltInFieldId.Title].ToString() == “Title To Search”);
[/csharp]

Share