In the past I’ve mentioned LINQ’s Cast<T>()
as an efficient way to convert a SharePoint collection into an IEnumerable<T>
that has access to LINQ’s various extension methods. Fundamentally, Cast<T>()
is implemented like this:
public IEnumerable<T> Cast<T>(this IEnumerable source) { foreach(object o in source) yield return (T) o; }
Using an explicit cast performs well, but will result in an InvalidCastException
if the cast fails. A less efficient yet useful variation on this idea is OfType<T>()
:
public IEnumerable<T> OfType<T>(this IEnumerable source) { foreach(object o in source) if(o is T) yield return (T) o; }
The returned enumeration will only include elements that can safely be cast to the specified type. Why would this be useful?
Example 1: SPWindowsServiceInstance
SharePoint, especially with MOSS, has several different services that can run on the various servers in a farm. We know where our web services are running, but where are the various windows services running?
var winsvc = from svr in SPFarm.Local.Servers from inst in svr.ServiceInstances.OfType<SPWindowsServiceInstance>() select new { Server = svr.Name, ID = inst.Id, ServiceType = inst.Service.GetType().Name };
Example 2: SPDocumentLibrary
SharePoint provides a few special subclasses of SPList
for specific kinds of lists. These include SPDocumentLibrary
, SPPictureLibrary
and the essentially obsolete SPIssueList
. We can use OfType()
to retrieve only lists of a certain type, like this LINQified MSDN sample that enumerates all files in a site collection’s libraries, excluding catalogs and form libraries:
SPSite site = SPContext.Current.Site; var docs = from web in site.AllWebs.AsSafeEnumerable() from lib in web.Lists.OfType<SPDocumentLibrary>() from SPListItem doc in lib.Items where !lib.IsCatalog && lib.BaseTemplate != SPListTemplateType.XMLForm select new { WebTitle = web.Title, ListTitle = lib.Title, ItemTitle = doc.Fields.ContainsField("Title") ? doc.Title : "" }; foreach (var doc in docs) Label1.Text += SPEncode.HtmlEncode(doc.WebTitle) + " -- " + SPEncode.HtmlEncode(doc.ListTitle) + " -- " + SPEncode.HtmlEncode(doc.ItemTitle) + "<BR>";
Example 3: SPFieldUser
Finally, let’s pull a list of all user fields attached to lists in the root web. This could also be used to easily find instances of a custom field type.
var userFields = from SPList list in site.RootWeb.Lists from fld in list.Fields.OfType<SPFieldUser>() select new { ListTitle = list.Title, FieldTitle = fld.Title, InternalName = fld.InternalName, PresenceEnabled = fld.Presence };
Contrived examples, perhaps, but potentially useful nonetheless.