void Initialize()
        {
            var endpointRegistry = new EndpointRegistry();
            var handlerRegistry  = new HandlerRegistry();

            var messageTrees    = CreateMessageTrees(messages).ToArray();
            var messagesInOrder = messageTrees.SelectMany(x => x.Walk()).ToArray();

            // NOTE: All sending endpoints are created first to ensure version info is retained
            foreach (var message in messagesInOrder)
            {
                endpointRegistry.Register(CreateSendingEndpoint(message));
            }

            foreach (var message in messagesInOrder)
            {
                endpointRegistry.Register(CreateProcessingEndpoint(message));
            }

            foreach (var message in messagesInOrder)
            {
                var sendingEndpoint = endpointRegistry.Get(CreateSendingEndpoint(message));
                if (!endpoints.Contains(sendingEndpoint))
                {
                    endpoints.Add(sendingEndpoint);
                }

                var processingEndpoint = endpointRegistry.Get(CreateProcessingEndpoint(message));
                if (!endpoints.Contains(processingEndpoint))
                {
                    endpoints.Add(processingEndpoint);
                }

                Handler sendingHandler;
                Handler processingHandler;

                if (handlerRegistry.TryRegisterHandler(CreateSendingHandler(message, sendingEndpoint), out sendingHandler))
                {
                    handlers.Add(sendingHandler);
                    sendingEndpoint.Handlers.Add(sendingHandler);
                }

                sendingHandler.UpdateProcessedAtGuess(message.TimeSent);

                if (handlerRegistry.TryRegisterHandler(CreateProcessingHandler(message, processingEndpoint), out processingHandler))
                {
                    handlers.Add(processingHandler);
                    processingEndpoint.Handlers.Add(processingHandler);
                }
                else
                {
                    UpdateProcessingHandler(processingHandler, message, processingEndpoint);
                }

                var arrow = CreateArrow(message);
                arrow.ToHandler   = processingHandler;
                arrow.FromHandler = sendingHandler;

                var messageProcessingRoute = CreateRoute(arrow, processingHandler);
                arrow.MessageProcessingRoute = messageProcessingRoute;
                processingRoutes.Add(messageProcessingRoute);
                processingHandler.In = arrow;

                sendingHandler.Out = sendingHandler.Out.Concat(new[] { arrow }).OrderBy(a => a).ToList();
            }
        }
        void Initialize()
        {
            var endpointRegistry = new EndpointRegistry();
            var handlerRegistry = new HandlerRegistry();

            var messageTrees = CreateMessageTrees(messages).ToArray();
            var messagesInOrder = messageTrees.SelectMany(x => x.Walk()).ToArray();

            // NOTE: All sending endpoints are created first to ensure version info is retained
            foreach (var message in messagesInOrder)
            {
                endpointRegistry.Register(CreateSendingEndpoint(message));
            }

            foreach (var message in messagesInOrder)
            {
                endpointRegistry.Register(CreateProcessingEndpoint(message));
            }

            foreach (var message in messagesInOrder)
            {
                var sendingEndpoint = endpointRegistry.Get(CreateSendingEndpoint(message));
                if (!endpoints.Contains(sendingEndpoint))
                {
                    endpoints.Add(sendingEndpoint);
                }

                var processingEndpoint = endpointRegistry.Get(CreateProcessingEndpoint(message));
                if (!endpoints.Contains(processingEndpoint))
                {
                    endpoints.Add(processingEndpoint);
                }

                Handler sendingHandler;
                Handler processingHandler;

                if (handlerRegistry.TryRegisterHandler(CreateSendingHandler(message, sendingEndpoint), out sendingHandler))
                {
                    handlers.Add(sendingHandler);
                    sendingEndpoint.Handlers.Add(sendingHandler);
                }

                sendingHandler.UpdateProcessedAtGuess(message.TimeSent);

                if (handlerRegistry.TryRegisterHandler(CreateProcessingHandler(message, processingEndpoint), out processingHandler))
                {
                    handlers.Add(processingHandler);
                    processingEndpoint.Handlers.Add(processingHandler);
                }
                else
                {
                    UpdateProcessingHandler(processingHandler, message, processingEndpoint);
                }

                var arrow = CreateArrow(message);
                arrow.ToHandler = processingHandler;
                arrow.FromHandler = sendingHandler;

                var messageProcessingRoute = CreateRoute(arrow, processingHandler);
                arrow.MessageProcessingRoute = messageProcessingRoute;
                processingRoutes.Add(messageProcessingRoute);
                processingHandler.In = arrow;

                sendingHandler.Out = sendingHandler.Out.Concat(new[] { arrow }).OrderBy(a => a).ToList();
            }
        }