/// <summary>
        /// Performs the Search given the <paramref name="solver"/>.
        /// </summary>
        /// <param name="solver"></param>
        /// <returns></returns>
        private Solver PerformSearch(Solver solver)
        {
            // TODO: TBD: depending on the kind of collector, first, last, all, etc, may want to rethink this approach a bit...
            // TODO: TBD: particularly in how/when we process the assignments/variables...
            var collection = new ReadOnlyAssignmentCollection(Collector);

            // Evaluate Variables as an Array once.
            var variables = Variables.ToArray();

            // The Solver should be set but let's double check that just in case.
            while (solver?.NextSolution() == true)
            {
                // TODO: TBD: the only thing I don't like about this is the overhead involved maintaining events/handlers/args, etc
                if (OnPredicated().ShouldBreak)
                {
                    break;
                }

                if (OnNextAssignment(collection).ShouldBreak)
                {
                    break;
                }

                if (OnProcessVariables(variables).ShouldBreak)
                {
                    break;
                }
            }

            return(solver);
        }
        private ReceiveAssignmentEventArgs OnNextAssignment(ReadOnlyAssignmentCollection collection)
        {
            // Only engage the collection and potentially invoke the event when we have something to invoke.
            if (NextAssignment == null || !(collection.HasCollector && collection.Any()))
            {
                return(new ReceiveAssignmentEventArgs(Solver));
            }
            var e = new ReceiveAssignmentEventArgs(Solver, collection[collection.Count - 1]);

            NextAssignment(this, e);
            return(e);
        }