/// <summary>
        ///     Gets <see cref="ICompletes{TResult}" />, applying <paramref name="state" />,
        ///     dispatching to <code>State(T state)</code> when completed, and supply an
        ///     eventual outcome by means of the given <code>andThen</code> function.
        /// </summary>
        /// <param name="state">The state to preserve.</param>
        /// <param name="andThen">
        ///     The <see cref="CompletionSupplier{TResult}" /> that will provide the fully updated state following this operation,
        ///     and which will used to answer an eventual outcome to the client of this entity
        /// </param>
        /// <typeparam name="TSource">The type of the source.</typeparam>
        /// <typeparam name="TResult">The return type of the Supplier function, which is the type of the completed state.</typeparam>
        /// <returns><see cref="ICompletes{TResult}" />.</returns>
        protected ICompletes <TResult> Apply <TSource, TResult>(T state, Func <TResult>?andThen)
        {
            var completionSupplier = CompletionSupplier <TResult> .SupplierOrNull(andThen, CompletesEventually());

            var completes = andThen == null ? null : Completes();

            StowMessages(typeof(IPersistResultInterest));
            _info.Store.Persist(StateSources <T, Source <TSource> > .Of(state), _persistResultInterest, completionSupplier);
            return((ICompletes <TResult>)completes !);
        }
        /// <summary>
        ///     Gets <see cref="ICompletes{TResult}" />, applying <paramref name="state" /> and <paramref name="metadataValue" />,
        ///     that was modified due to the descriptive <paramref name="operation"/> and
        ///     eventual outcome by means of the given <code>andThen</code> function.
        /// </summary>
        /// <param name="state">The state to apply.</param>
        /// <param name="metadataValue">The Metadata to apply along with the state.</param>
        /// <param name="operation">The descriptive name of the operation that caused the state modification.</param>
        /// <param name="andThen">
        ///     The <see cref="CompletionSupplier{TReturn}" /> that will provide the fully updated state following this operation,
        ///     and which will used to answer an eventual outcome to the client of this entity
        /// </param>
        /// <typeparam name="TResult">The return type of the Supplier function, which is the type of the completed state.</typeparam>
        /// <returns><see cref="ICompletes{TResult}" />.</returns>
        protected virtual ICompletes <TResult> Apply <TResult>(T state, string?metadataValue, string?operation, Func <TResult>?andThen)
        {
            var metadata           = Metadata.With(state !, metadataValue ?? "", operation ?? "");
            var completionSupplier = CompletionSupplier <T> .SupplierOrNull(andThen, CompletesEventually());

            var completes = andThen == null ? null : Completes();

            StowMessages(typeof(IWriteResultInterest));
            _info.Store.Write(Id, state, NextVersion(), metadata, _writeInterest, completionSupplier);
            return((ICompletes <TResult>)completes !);
        }
        public void TestThatFailedHasExceptionInfo()
        {
            var cause      = new Exception("TestInner", new Exception());
            var applicable = new Applicable <object>(null, Enumerable.Empty <ISource>(), Metadata.NullMetadata(), CompletionSupplier <object> .SupplierOrNull <object>(() => null, null));
            var e          = new ApplyFailedException <object>(applicable, "TestOuter", cause);

            Assert.NotNull(e);
            Assert.NotNull(e.Applicable);
            Assert.Equal("TestOuter", e.Message);
            Assert.NotNull(e.InnerException);
            Assert.Equal("TestInner", e.InnerException.Message);
            Assert.NotNull(e.Message);
            Assert.NotNull(e.InnerException.InnerException);
            Assert.Equal("Exception of type 'System.Exception' was thrown.", e.InnerException.InnerException.Message);
        }
        public void TestThatFailedHasApplicable()
        {
            var applicable = new Applicable <object>(null, Enumerable.Empty <ISource>(), Metadata.NullMetadata(), CompletionSupplier <object> .SupplierOrNull <object>(() => null, null));
            var e          = new ApplyFailedException <object>(applicable);

            Assert.NotNull(e);
            Assert.NotNull(e.Applicable);
            Assert.Null(e.Applicable.State);
            Assert.NotNull(e.Applicable.Sources);
            Assert.NotNull(e.Applicable.Metadata);
            Assert.NotNull(e.Applicable.CompletionSupplier);
            Assert.Equal("Exception of type 'Vlingo.Xoom.Lattice.Model.ApplyFailedException`1[System.Object]' was thrown.", e.Message);
            Assert.Null(e.InnerException);
        }