/// <summary>
        /// An implementation of the tunnel routing strategy which uses reflection rather than
        /// dynamic runtime code generation.
        /// </summary>
        private static void ReflectionBasedImplementationForTunnelStrategy(RoutedEvent evt, Object[] parameters)
        {
            var index   = 0;
            var handler = default(RoutedEventHandlerMetadata);
            var element = (DependencyObject)parameters[0];
            var current = default(DependencyObject);
            var data    = (RoutedEventData)parameters[parameters.Length - 1];
            var stack   = default(Stack <DependencyObject>);

            while (ShouldContinueTunnelling(element, ref current, ref stack))
            {
                index = 0;
                while (GetEventHandler(current, evt, ref index, ref handler))
                {
                    if (ShouldEventBeRaisedForElement(data, handler.HandledEventsToo))
                    {
                        parameters[0] = current;
                        handler.Handler.DynamicInvoke(parameters);
                    }
                }

                evt.RaiseRaisedNotification(current, data);
            }

            ReleaseTunnellingStack(stack);

            if (data.AutoRelease)
            {
                data.Release();
            }
        }
        /// <summary>
        /// An implementation of the direct routing strategy which uses reflection rather than
        /// dynamic runtime code generation.
        /// </summary>
        private static void ReflectionBasedImplementationForDirectStrategy(RoutedEvent evt, Object[] parameters)
        {
            var index   = 0;
            var handler = default(RoutedEventHandlerMetadata);

            var element = (DependencyObject)parameters[0];
            var data    = (RoutedEventData)parameters[parameters.Length - 1];

            while (GetEventHandler(element, evt, ref index, ref handler))
            {
                if (ShouldEventBeRaisedForElement(data, handler.HandledEventsToo))
                {
                    handler.Handler.DynamicInvoke(parameters);
                }
            }

            evt.RaiseRaisedNotification(element, data);

            if (data.AutoRelease)
            {
                data.Release();
            }
        }
        /// <summary>
        /// An implementation of the tunnel routing strategy which uses reflection rather than
        /// dynamic runtime code generation.
        /// </summary>
        private static void ReflectionBasedImplementationForTunnelStrategy(RoutedEvent evt, Object[] parameters)
        {
            var index = 0;
            var handler = default(RoutedEventHandlerMetadata);
            var element = (DependencyObject)parameters[0];
            var current = default(DependencyObject);
            var data = (RoutedEventData)parameters[parameters.Length - 1];

            while (ShouldContinueTunnelling(element, ref current))
            {
                index = 0;
                while (GetEventHandler(current, evt, ref index, ref handler))
                {
                    if (ShouldEventBeRaisedForElement(data, handler.HandledEventsToo))
                    {
                        parameters[0] = current;
                        handler.Handler.DynamicInvoke(parameters);
                    }
                }

                evt.RaiseRaisedNotification(current, data);
            }

            if (data.AutoRelease)
                data.Release();
        }