Skip to content

Using event raising collection wrappers

Craig Fowler edited this page Dec 2, 2016 · 2 revisions

There are presently three available implementations of event-raising collection wrappers (much like the event-raising collections they wrap). You are also welcome to write/contribute your own.

  • CSF.Collections.EventRaising.EventRaisingCollectionWrapper<T>
  • CSF.Collections.EventRaising.EventRaisingListWrapper<T>
  • CSF.Collections.EventRaising.EventRaisingSetWrapper<T>

Each of these wrapper types targets a corresponding event-raising collection. Each also offers two public constructors, one empty and another which permits passing in the source collection. The empty constructor initialises the collection with an initial state of null, that is - it does not contain a wrapped collection.

Much like the event-raising collection types themselves, the wrappers deal with a source collection and an event-raising collection. The source collection is the "real" (unmodified) collection instance and the event-raising collection is an object which extends the functionality of the source. The wrapper type extends that further by allowing events for the replacement of the collection itself with a totally new instance.

API of a collection wrapper

All of the collection wrappers provide the following properties:

  • Collection (get-only)
  • SourceCollection (get & set)

The Collection property is the event-raising collection instance, which raises events when it its state is modified. This is the property you expose on your public API. The SourceCollection property, on the other hand, is typically hidden (private or protected) in your API and only available publicly via a property setter or replacement method.

A collection wrapper also exposes copies of all of the events which the event-raising collection exposes, as well as two additional ones. Much like the collection's events, these are triggered before and after usage of the SourceCollection's setter:

  • BeforeReplace
  • AfterReplace

When using a collection wrapper, you should bind/subscribe to the wrapper's event and not the events on the collection it wraps. Because the wrapper itself is never replaced (even when the event-raising collection it wraps is replaced), its events and their subscriptions 'live on' after replacing the collection with a different instance.

Example

The Collection property exposes the event-raising collection and the SourceCollection exposes the source/original collection. This allows us to make our collection implementations writable on our implementation classes as such:

using CSF.Collections.EventRaising;
using System.Collections.Generic;

public class Parent()
{
  private IList<Child> _sourceChildren;
  private EventRaisingListWrapper<Child> _childrenWrapper;

  public Parent()
  {
    _sourceChildren = new List<Child>();
    _childrenWrapper = new EventRaisingListWrapper<Child>(_sourceChildren);

    // Set up bindings to the wrapper instance's events here
  }

  public IList<Child> Children {
    get { return _children.Collection; }
    set { _children.SourceCollection = value; }
  }
}

In this example, when the Children property is set, the wrapper takes care of replacing the source collection, and re-initialising the event-raising collection.

The before/after replace events

The before and after replace events use the signatures AfterReplaceEventArgs<TCollection> and BeforeReplaceEventArgs<TCollection>. Both of these event args types provide the properties Original and Replacement. These allow the inspection of the original collection (which is to be discarded) and its replacement instance. The before event args also provides the read-only boolean property IsCancelled and a method named Cancel. The extra functionality available before the collection is replaced allows the cancelling of the replacement. Whilst this offers a powerful way to whether or not a collection may be replaced, please consider very carefully whether it is appropriate before making use of it.