Provides undo and redo services.
Inheritance: IDisposable
        public void when_attempting_to_version_a_property_bag()
        {
            var originalAddress = "12345 Fake Street";
            var subscriber = new SimpleMementoingClass()
                                 {
                                     Domainees = new List<DomainPropertyBag>()
                                                     {
                                                         new DomainPropertyBag(),
                                                         new DomainPropertyBag()
                                                     },
                                     ChiefDomainee = new DomainPropertyBag(),
                                     Address = originalAddress,
                                     FirstName = "If only Customer Objects",
                                     LastName = "were ever this simple"
                                 };

            var mementor = new Mementor();

            var newAddress = "Changed Address!";
            mementor.PropertyChange(subscriber, () => subscriber.Address);
            //ohhh typing is a little weak here.
            subscriber.Address = newAddress; //ahh, note the order matters of course.

            subscriber.Address.Should().Be(newAddress);

            mementor.Undo();
            //and I cant undo specific changes, just the last one.

            subscriber.Address.Should().Be(originalAddress);
            //still, very cool.
                //In terms of a deployed program, this is tough to implement.
                //I like the pub-sub design of it, code is superbly clean.
        }
 /// <summary>
 /// Marks an element index change event.
 /// </summary>
 /// <typeparam name="T">The generic type parameter of the collection.</typeparam>
 /// <param name="mementor">The mementor object.</param>
 /// <param name="collection">The collection object.</param>
 /// <param name="element">The element whose index is being changed</param>
 /// <param name="elementIndex">The index of the element being removed. If not supplied, will retrieve via <see cref="IList{T}.IndexOf"/>.</param>
 public static void ElementIndexChange <T>(this Mementor mementor,
                                           IList <T> collection, T element, int?elementIndex = null)
 {
     if (mementor.IsTrackingEnabled)
     {
         mementor.MarkEvent(new ElementIndexChangeEvent <T>(collection, element, elementIndex));
     }
 }
 /// <summary>
 /// Marks an element addition event.
 /// </summary>
 /// <typeparam name="T">The generic type parameter of the collection.</typeparam>
 /// <param name="mementor">The mementor object.</param>
 /// <param name="collection">The collection object.</param>
 /// <param name="element">The element being added.</param>
 public static void ElementAdd <T>(this Mementor mementor,
                                   IList <T> collection, T element)
 {
     if (mementor.IsTrackingEnabled)
     {
         mementor.MarkEvent(new ElementAdditionEvent <T>(collection, element));
     }
 }
 /// <summary>
 /// Marks a property change event.
 /// </summary>
 /// <param name="mementor">The mementor object.</param>
 /// <param name="target">The target object.</param>
 /// <param name="propertyName">The name of the property.</param>
 /// <param name="previousValue">The value to be restored to when undo.
 /// If not supplied, will be retrieved directly from the <paramref name="target"/>.</param>
 public static void PropertyChange(this Mementor mementor,
                                   object target, string propertyName, object previousValue = null)
 {
     if (mementor.IsTrackingEnabled)
     {
         mementor.MarkEvent(new PropertyChangeEvent(target, propertyName, previousValue));
     }
 }
 /// <summary>
 /// Marks a property change event.
 /// </summary>
 /// <typeparam name="TProp">The type of the property.</typeparam>
 /// <param name="mementor">The mementor object.</param>
 /// <param name="target">The target object.</param>
 /// <param name="propertySelector">The property selector expression.</param>
 /// <param name="previousValue">The value to be restored to when undo.
 /// If not supplied, will be retrieved directly from the <paramref name="target"/>.</param>
 public static void PropertyChange <TProp>(this Mementor mementor,
                                           object target, Expression <Func <TProp> > propertySelector, object previousValue = null)
 {
     if (mementor.IsTrackingEnabled)
     {
         PropertyChange(mementor, target, propertySelector.Name(), previousValue);
     }
 }
        public void when_forcing_bad_things_via_expression()
        {
            var subscriber = new SimpleMementoingClass();
            var mementor = new Mementor();

            subscriber.Address = "Changed!";
            Assert.Throws<InvalidCastException>(() => mementor.PropertyChange(subscriber, () => mementor.ToString()));
            //aww duder and the exceptions arn't handled nicely here either, Linq at the wrong thing and get a generic Expression.OhgodohgodohgodException
                //why not public void PropertyChange<TSubject, TTargetSite>(this TSubject subject, Func<TSubject, TTargetSite> transform...)
                    //would be mementor.PropertyChange(subscriber, sub => sub.SomeProp), would provide some additional typiing on the expression.
        }
        public void when_attempting_to_restore_an_externally_tracked_list()
        {
            var mementor = new Mementor(isEnabled: true);

            var collection = new List<string>();
            var item = "hey!";
            mementor.ElementAdd(collection, item);//this is an extension method? Oh I see, he didnt want to put custom-list logic on Mementor. Nice.
            //it also doesnt actually add the element to the list:
            collection.Add(item);
            collection.Should().HaveCount(1);

            mementor.Undo();
            //hmm, so it expects the caller to do the Add but it will handle the remove?

            collection.Should().BeEmpty();
        }