public void ObserveEvents()
            {
                var methodsWithAttributes =
                    from methodInfo in _eventProcessor.GetType().GetMethodsRecursive(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
                    let observeEventAttributes = methodInfo.GetCustomAttributes <ObserveEventAttribute>(true).ToArray()
                                                 where observeEventAttributes.Length > 0
                                                 select new { methodInfo, observeEventAttributes };

                foreach (var methodWithAttributes in methodsWithAttributes)
                {
                    ObserveEventAttribute[] observeEventAttributes = methodWithAttributes.observeEventAttributes;
                    MethodInfo method = methodWithAttributes.methodInfo;

                    if (observeEventAttributes.Length == 1)
                    {
                        ObserveEventAttribute observeEventAttribute = observeEventAttributes[0];
                        EnsureObserveEventSignatureCorrect(method, observeEventAttribute.EventType);
                        var eventObservable = CreateEventObservable(observeEventAttribute);
                        var observeDelegate = CreateEventObserverDelegate(method, observeEventAttribute.EventType);
                        ObserveEvent(eventObservable, observeDelegate);
                    }
                    else
                    {
                        var baseEventType = GetBaseEventType(method, observeEventAttributes);
                        EnsureObserveEventSignatureCorrect(method, baseEventType);
                        var eventObservable = CreateEventObservable(baseEventType, observeEventAttributes);
                        var observeDelegate = CreateEventObserverDelegate(method, baseEventType);
                        ObserveEvent(eventObservable, observeDelegate);
                    }
                }
            }
            // gets a merged IEventObservable<TEvent, TContext, TModel> for all events in the given attributes, the merged streams TEvent is of baseEventType
            private object CreateEventObservable(Type baseEventType, ObserveEventAttribute[] observeEventAttributes)
            {
                var eventObservableType = typeof(IEventObservable <, ,>).MakeGenericType(new Type[] { baseEventType, typeof(IEventContext), typeof(TModel) });
                var eventObservables    = (IList)typeof(List <>)
                                          .MakeGenericType(eventObservableType)
                                          .GetConstructor(new Type[] {})
                                          .Invoke(null);

                for (int i = 0; i < observeEventAttributes.Length; i++)
                {
                    ObserveEventAttribute observeEventAttribute = observeEventAttributes[i];
                    dynamic eventObservable = CreateEventObservable(observeEventAttribute);
                    eventObservables.Add(eventObservable);
                }
                MethodInfo closedEventObservableMergeMethod = ObservableMergeMethodInfo.MakeGenericMethod(new Type[] { baseEventType, typeof(IEventContext), typeof(TModel) });

                return(closedEventObservableMergeMethod.Invoke(null, new object[] { eventObservables }));
            }
            // gets an IEventObservable<TEvent, TContext, TModel> for the details in the given attribute
            private object CreateEventObservable(ObserveEventAttribute observeEventAttribute)
            {
                var getEventObservableMethod = GetEventObservableMethodInfo.MakeGenericMethod(observeEventAttribute.EventType);

                return(getEventObservableMethod.Invoke(_router, new object[] { observeEventAttribute.Stage }));
            }