In versioning attachments in a SharePoint list using snapshotting, an event receiver was responsible for the heavy lifting. To enable versioning of a list, I could therefore have associated the receiver with a list by adding the usual registration XML to a feature. But versioning is a truly reusable building block that shouldn’t be restricted to lists that are known when the feature is created. A better solution would be to extend the SharePoint list settings page for all lists on a site on which the versioning feature is enabled. The user may then activate or deactivate attachment versioning on the fly.
This would involve adding or removing event receivers from a list as the user enables or disables versioning. The following extension method is one way to accomplish the addition-part in a type-safe manner:
// definition public static class SPListExtensions { public static void RegisterEventReceiver<TReceiver>(this SPList list, SPEventReceiverType receiverType, int sequenceNumber) where TReceiver : SPItemEventReceiver { var assemblyName = typeof(TReceiver).Assembly.FullName; var className = typeof(TReceiver).FullName; (from SPEventReceiverDefinition definition in list.EventReceivers where definition.Assembly == assemblyName && definition.Class == className && definition.Type == receiverType select list.EventReceivers[definition.Id]) .ToList() .ForEach(receiverToDelete => receiverToDelete.Delete()); var receiver = list.EventReceivers.Add(); receiver.Type = receiverType; receiver.Assembly = assemblyName; receiver.Class = className; receiver.SequenceNumber = sequenceNumber; receiver.Update(); list.Update(); } } // use list.RegisterEventReceiver<ListAttachmentVersioningEventReceiver>( SPEventReceiverType.ItemAdded, 10000); list.RegisterEventReceiver<ListAttachmentVersioningEventReceiver>( SPEventReceiverType.ItemUpdated, 10001);
Under rare circumstances the (assembly, class, type) tuple may not be unique, i.e., the same receiver may be registered multiple times, albeit with different sequence numbers. In practice I never found any use for this functionality, though, which is why I didn’t include the sequence number in the where clause above, causing all registrations matching the tuple to be removed.