/// <summary>
        /// Dispatches the message by forwarding it according to the routing rules.
        /// </summary>
        /// <param name="message">The message.</param>
        public void DispatchMessage(ImmutableEnvelope message)
        {
            var route = _routerRule(message);

            // allow discarding messages, if explicitly allowed
            if (route == "memory:null")
            {
                return;
            }


            var    items = route.Split(new[] { ':' }, 2);
            string queueName;
            string endpoint;

            if (items.Length == 1)
            {
                queueName = route;
                endpoint  = "default";
            }
            else
            {
                endpoint  = items[0];
                queueName = items[1];
            }

            IQueueWriterFactory factory;

            if (!_queueRegistry.TryGet(endpoint, out factory))
            {
                var s = string.Format(
                    "Route '{0}' was not handled by any single dispatcher. Did you want to send to 'memory:null' or 'memory:{0}' instead? Please, read documentation on Routing Dispatcher.",
                    route);
                throw new InvalidOperationException(s);
            }
            factory.GetWriteQueue(queueName).PutMessage(message);
            return;
        }
        void Dispatch(string id, IEnumerable <ICommand> commands)
        {
            var stream = _factory.GetOrCreateStream(id);

            var records = stream.ReadRecords(0, int.MaxValue).ToList();
            var events  = records
                          .Select(tr => _streamer.ReadAsEnvelopeData(tr.Data))
                          .SelectMany(i => i.Items)
                          .Select(i => (IEvent)i.Content)
                          .ToList();

            var then = AggregateFactory
                       .LoadProject(events, commands)
                       .Select(e => new MessageBuilder(e.GetType(), e)).ToList();

            if (then.Count == 0)
            {
                return;
            }


            // events are stored here as envelopes )
            var b = new EnvelopeBuilder("unknown");

            foreach (var e in then)
            {
                b.Items.Add(e);
            }

            var version = records.Count == 0 ? 0 : records.Last().Version;

            var data   = _streamer.SaveEnvelopeData(b.Build());
            var result = stream.TryAppend(data, TapeAppendCondition.VersionIs(version));

            if (!result)
            {
                throw new InvalidOperationException(
                          "Data was modified concurrently, and we don't have merging implemented, yet");
            }

            var args = _path.Split(':');
            IQueueWriterFactory factory;

            if (!_queue.TryGet(args[0], out factory))
            {
                throw new InvalidOperationException("Not found " + _path);
            }


            var arVersion = events.Count + 1;
            var arName    = id;

            for (int i = 0; i < then.Count; i++)
            {
                var name    = string.Format("{0}/{1}/{2}", arName, arVersion, i);
                var builder = new EnvelopeBuilder(name);


                builder.Items.Add(then[i]);
                builder.AddString("from-entity", arName);

                factory.GetWriteQueue(args[1]).PutMessage(builder.Build());
            }
        }