Esempio n. 1
0
        /// <summary>
        /// Registers a new event handler.
        /// Any other event handlers that the <paramref name="eventHandler"/> instance might implement, will be ignored.
        /// </summary>
        /// <typeparam name="TEvent">The type of event to add a handler for.</typeparam>
        /// <param name="eventHandler">The event handler to add.</param>
        /// <param name="weakRef"><c>true</c> to store a weak reference; <c>false</c> to store a strong reference.</param>
        /// <returns><c>true</c> if this specific event handler was not yet registered; otherwise, <c>false</c>.</returns>
        public bool Add <TEvent>(IEventHandler <TEvent> eventHandler, bool weakRef = true)
            where TEvent : EventBase
        {
            if (eventHandler.NullReference())
            {
                throw Exc.Null(nameof(eventHandler));
            }

            lock (this.subscribers)
            {
                if (this.isClosed)
                {
                    return(false);
                }

                // do nothing if this handler is already registered
                if (this.IndexOfSpecificEventHandler <TEvent>(eventHandler) != -1)
                {
                    return(false);
                }

                // wrap handler
                var newWrapper = EventHandlerWrapper.Create <TEvent>(eventHandler, weakRef);

                // register wrapper
                this.subscribers.Add(newWrapper);
                return(true);
            }
        }
Esempio n. 2
0
        /// <summary>
        /// Executes the specified <see cref="Action"/> asynchronously on the UI thread.
        /// </summary>
        /// <param name="func">The delegate to invoke.</param>
        /// <returns>The <see cref="Task"/> representing the operation.</returns>
        public static Task <T> InvokeAsync <T>(Func <T> func)
        {
            if (func.NullReference())
            {
                throw Exc.Null(nameof(func));
            }

            ThrowIfNoThread();

            var tsc = new TaskCompletionSource <T>();

            uiThread.BeginInvoke(
                () =>
            {
                try
                {
                    var result = func();
                    tsc.SetResult(result);
                }
                catch (Exception ex)
                {
                    ex.StoreFileLine();
                    tsc.SetException(ex);
                }
            });
            return(tsc.Task);
        }
Esempio n. 3
0
        /// <summary>
        /// Parses a string produced using <see cref="Compact"/>.
        /// </summary>
        /// <param name="str">The string to parse.</param>
        /// <param name="file">The file name in <paramref name="str"/>.</param>
        /// <param name="member">The member name in <paramref name="str"/>.</param>
        /// <param name="line">The line number in <paramref name="str"/>.</param>
        public static void ParseCompact(string str, out string file, out string member, out int line)
        {
            if (str.NullReference())
            {
                throw Exc.Null(nameof(str));
            }

            int memberAt = str.IndexOf(',');

            if (memberAt == -1)
            {
                throw new FormatException().Store(nameof(str), str);
            }
            else
            {
                member = str.Substring(startIndex: 0, length: memberAt).Trim();
            }

            int lineAt = str.LastIndexOf(':');

            if (lineAt == -1)
            {
                throw new FormatException().Store(nameof(str), str);
            }
            else if (!int.TryParse(str.Substring(startIndex: lineAt + 1), NumberStyles.Integer, CultureInfo.InvariantCulture, out line))
            {
                throw new FormatException().Store(nameof(str), str);
            }

            file = str.Substring(startIndex: memberAt + 1, length: lineAt - memberAt - 1).Trim();
        }
Esempio n. 4
0
            /// <summary>
            /// Converts the specified object to a <see cref="string"/>.
            /// Does not return <c>null</c>.
            /// </summary>
            /// <param name="obj">The object to convert to a string.</param>
            /// <returns>The string representation of the specified object. Never <c>null</c>.</returns>
            public string ToString(string obj)
            {
                if (obj.NullReference())
                {
                    throw Exc.Null(nameof(obj));
                }

                return(obj);
            }
Esempio n. 5
0
        /// <summary>
        /// Adds a weak reference to the specified object, to this collection.
        /// </summary>
        /// <param name="obj">The object to store a weak reference of.</param>
        public void Add(T obj)
        {
            if (obj.NullReference())
            {
                throw Exc.Null(nameof(obj));
            }

            this.Add(new WeakReference <T>(obj));
        }
Esempio n. 6
0
            internal WeakEventHandlerWrapper(IEventHandler <TEvent> subscriber)
            {
                if (subscriber.NullReference())
                {
                    throw Exc.Null(nameof(subscriber));
                }

                this.weakRef = new WeakReference <IEventHandler <TEvent> >(subscriber);
            }
Esempio n. 7
0
        /// <summary>
        /// Initializes a new instance of the <see cref="DispatcherUIThread"/> class.
        /// </summary>
        /// <param name="uiDispatcher">The UI <see cref="Dispatcher"/>.</param>
        /// <param name="priority">The priority, relative to the other pending operations in the <see cref="T:System.Windows.Threading.Dispatcher" /> event queue, to invoke delegates with.</param>
        public DispatcherUIThread(Dispatcher uiDispatcher, DispatcherPriority priority = DispatcherPriority.Normal)   // the priority used by Dispatcher.BeginInvoke(method, args)
        {
            if (!Enum.IsDefined(typeof(DispatcherPriority), priority))
            {
                throw new ArgumentException($"Unknown dispatcher priority: {priority}!");
            }

            this.dispatcher         = uiDispatcher ?? throw Exc.Null(nameof(uiDispatcher));
            this.dispatcherPriority = priority;
        }
        private EventSubscriberTypeInfo(Type subscriberType)
        {
            this.Type     = subscriberType ?? throw Exc.Null(nameof(subscriberType));
            this.TypeInfo = this.Type.GetTypeInfo();

            var types = GetEventHandlerTypes(this.Type);

            this.EventHandlerTypes = new ReadOnlyCollection <Type>(types);
            this.HandledEventTypes = new ReadOnlyCollection <Type>(GetHandledEventTypes(types));
        }
Esempio n. 9
0
        /// <summary>
        /// Searches the subscriber for event handlers it implements, and removes any that can be found.
        /// </summary>
        /// <param name="subscriber">The subscriber to remove the event handlers of.</param>
        /// <returns><c>true</c> if at least one event handler was removed; <c>false</c> if none could be found.</returns>
        public bool RemoveAll(object subscriber)
        {
            if (subscriber.NullReference())
            {
                throw Exc.Null(nameof(subscriber));
            }

            var subscriberTypeInfo = EventSubscriberTypeInfo.AddOrGet(subscriber.GetType());

            return(subscriberTypeInfo.RemoveAll(this, subscriber));
        }
Esempio n. 10
0
        /// <summary>
        /// Searches the subscriber for event handlers it implements,
        /// and adds those that were not yet registered.
        /// </summary>
        /// <param name="subscriber">The subscriber to add the event handlers of.</param>
        /// <param name="weakRef"><c>true</c> to store weak references; <c>false</c> to store strong references.</param>
        /// <returns><c>true</c> if at least one event handler was added; otherwise, <c>false</c>.</returns>
        public bool AddAll(object subscriber, bool weakRef = true)
        {
            if (subscriber.NullReference())
            {
                throw Exc.Null(nameof(subscriber));
            }

            var subscriberTypeInfo = EventSubscriberTypeInfo.AddOrGet(subscriber.GetType());

            return(subscriberTypeInfo.AddAll(this, subscriber, weakRef));
        }
Esempio n. 11
0
        /// <summary>
        /// The window will not be closed while the main event queue is running,
        /// and shutting down the main event queue will shut down the window as well.
        /// </summary>
        /// <param name="window">The <see cref="Window"/> to bind to the main event queue.</param>
        public static void BindWindowToAppLifeCycle(Window window)
        {
            if (window.NullReference())
            {
                throw Exc.Null(nameof(window));
            }

            var windowCloseHandler = new WindowCloseHandler(window);

            MainEventQueue.Subscribers.Add <ShutDownEvent>(windowCloseHandler, weakRef: false); // a strong ref. for the handler, but a weak ref. for the window
        }
Esempio n. 12
0
        /// <summary>
        /// Invoked before the event is added to the <see cref="IEventQueueStorage"/>.
        /// Can optionally cancel the the adding.
        /// </summary>
        /// <param name="evnt">The event about to be added to the queue.</param>
        /// <param name="file">The source file of the caller.</param>
        /// <param name="member">The method or property name of the caller to this method.</param>
        /// <param name="line">The line number in <paramref name="file"/>.</param>
        /// <param name="canAdd">Determines whether the event can be added to the queue.</param>
        protected virtual void BeforeAdding(
            EventBase evnt,
            string file,
            string member,
            int line,
            out bool canAdd)
        {
            if (evnt.NullReference())
            {
                throw Exc.Null(nameof(evnt));
            }

            lock (this.syncLock)
            {
                // already enqueued?
                if (this.Storage.Contains(evnt))
                {
                    canAdd = false;
                    return;
                }

                // shutdown request event?
                if (evnt is ShutdownRequestEvent)
                {
                    if (this.shutdownRequestEnqueued || // another request is already enqueued or being handled
                        (this.eventsState >= State.ShuttingDownEnqueued))  // we are already shutting down, there is no question about it
                    {
                        canAdd = false;
                        return;
                    }
                    else
                    {
                        this.shutdownRequestEnqueued = true;
                    }
                }
                else if (evnt is ShuttingDownEvent)  // shutting down event?
                {
                    if (this.eventsState >= State.ShuttingDownEnqueued)
                    {
                        // another shutting down event already enqueued
                        canAdd = false;
                        return;
                    }
                    else
                    {
                        this.eventsState = State.ShuttingDownEnqueued;
                    }
                }

                evnt.EventEnqueuePos = FileLine.Compact(file, member, line);
                canAdd = true;
            }
        }
Esempio n. 13
0
        public static void Null()
        {
            Assert.NotNull(Exc.Null("test"));
            Assert.NotNull(Exc.Null(string.Empty));
            Assert.NotNull(Exc.Null(null));

            const string guid      = "d5b5b296e9dd4f60a164e92deceeb530";
            var          exception = Exc.Null(guid);

            Assert.IsInstanceOf <ArgumentNullException>(exception);
            Assert.True(exception.Message.Contains(guid));
        }
Esempio n. 14
0
        /// <summary>
        /// Adds the specified <see cref="WeakReference{T}"/> to this collection.
        /// The <see cref="WeakReference{T}"/> itself is stored using a strong reference.
        /// </summary>
        /// <param name="weakRef">The <see cref="WeakReference{T}"/> to add.</param>
        public void Add(WeakReference <T> weakRef)
        {
            if (weakRef.NullReference())
            {
                throw Exc.Null(nameof(weakRef));
            }

            //// NOTE: we are not checking whether the weak reference is still alive,
            ////       since the assumption is that it was recently created (e.g. by one of our other members).

            this.list.Add(weakRef);
        }
Esempio n. 15
0
        /// <summary>
        /// Initializes a new instance of the <see cref="UnhandledExceptionEvent"/> class.
        /// </summary>
        /// <param name="exception">The exception to report.</param>
        public UnhandledExceptionEvent(Exception exception)
        {
            if (exception.NullReference())
            {
                throw Exc.Null(nameof(exception));
            }

            this.Initialize(
                type: exception.GetType().ToString(),
                message: exception.Message,
                full: ToString(exception));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="DispatcherEventQueue"/> class.
        /// </summary>
        /// <param name="uiDispatcher">The <see cref="Dispatcher"/> to use for event handling.</param>
        /// <param name="priority">The <see cref="DispatcherPriority"/> to use. Background priority is the default, to keep the UI snappy.</param>
        public DispatcherEventQueue(Dispatcher uiDispatcher, DispatcherPriority priority = DispatcherPriority.Background)
        {
            if (!Enum.IsDefined(typeof(DispatcherPriority), priority))
            {
                throw new ArgumentException("Invalid priority!");
            }

            this.dispatcher              = uiDispatcher ?? throw Exc.Null(nameof(uiDispatcher));
            this.dispatcherPriority      = priority;
            this.isEventHandlerScheduled = new ThreadSafeBoolean(false);
            this.manualQueue             = new ManualEventQueue();
            this.scheduledDelegate       = new Action(this.OnScheduled);
        }
        /// <summary>
        /// Tries to add the specified event to the storage.
        /// The storage may refuse to store certain events
        /// (e.g. multiple <see cref="ShuttingDownEvent"/>s).
        /// </summary>
        /// <param name="evnt">The event to enqueue.</param>
        /// <returns><c>true</c> if the event was added to the storage; otherwise, <c>false</c>.</returns>
        public bool TryPush(EventBase evnt)
        {
            if (evnt.NullReference())
            {
                throw Exc.Null(nameof(evnt));
            }

            lock (this.syncLock)
            {
                this.events.Add(evnt);
                return(true);
            }
        }
Esempio n. 18
0
        /// <summary>
        /// Executes the specified <see cref="Action"/> asynchronously on the UI thread.
        /// </summary>
        /// <param name="action">The delegate to invoke.</param>
        public static void BeginInvoke(Action action)
        {
            if (action.NullReference())
            {
                throw Exc.Null(nameof(action));
            }

            ThrowIfNoThread();

            // NOTE: we're not checking whether we're already on the UI thread!
            //       even if we are, this method is supposed to be asynchronous.
            uiThread.BeginInvoke(action);
        }
Esempio n. 19
0
        /// <summary>
        /// Specifies the UI thread to use.
        /// May only set once at most.
        /// </summary>
        /// <param name="thread">The <see cref="IUIThread"/> to use.</param>
        public static void Set(IUIThread thread)
        {
            if (thread.NullReference())
            {
                throw Exc.Null(nameof(thread));
            }

            var previousValue = Interlocked.CompareExchange(ref uiThread, thread, comparand: null);

            if (previousValue.NotNullReference())
            {
                throw new InvalidOperationException("UI already initialized!").StoreFileLine();
            }
        }
Esempio n. 20
0
        /// <summary>
        /// Finds applicable subscribers, and has them handle the specified event, on the current thread.
        /// </summary>
        /// <param name="evnt">The event to handle.</param>
        /// <param name="exceptions">Stores exceptions throws by event handlers.</param>
        protected internal void Handle(EventBase evnt, List <Exception> exceptions)
        {
            if (evnt.NullReference())
            {
                throw Exc.Null(nameof(evnt));
            }

            if (exceptions.NullReference())
            {
                throw Exc.Null(nameof(exceptions));
            }

            lock (this.syncLock)
            {
                var eventTypeInfo = evnt.GetType().GetTypeInfo();
                for (int i = 0; i < this.subscribers.Count;)
                {
                    var wrapper = this.subscribers[i];
                    if (EventBase.CanHandle(wrapper.EventHandlerEventTypeInfo, eventTypeInfo))
                    {
                        bool referenceFound = true;
                        try
                        {
                            wrapper.Handle(evnt, out referenceFound);
                        }
                        catch (Exception ex)
                        {
                            exceptions.Add(ex);
                        }

                        if (referenceFound)
                        {
                            // event handled: continue
                            ++i;
                        }
                        else
                        {
                            // GC already collected the event handler: remove wrapper and continue
                            this.subscribers.RemoveAt(i);
                        }
                    }
                    else
                    {
                        // event handler not compatible with event: continue
                        ++i;
                    }
                }
            }
        }
Esempio n. 21
0
        /// <summary>
        /// Executes the specified <see cref="Action"/> asynchronously on the UI thread.
        /// </summary>
        /// <param name="action">The delegate to invoke.</param>
        /// <returns>The <see cref="Task"/> representing the operation.</returns>
        public static Task InvokeAsync(Action action)
        {
            if (action.NullReference())
            {
                throw Exc.Null(nameof(action));
            }

            object Wrapper()
            {
                action();
                return(null);
            }

            return(InvokeAsync <object>((Func <object>)Wrapper));
        }
Esempio n. 22
0
        internal MainEventQueue(EventQueueBase eventQueue)
        {
            if (eventQueue.NullReference())
            {
                throw Exc.Null(nameof(eventQueue));
            }

            if (eventQueue.IsShutDown)
            {
                throw new ArgumentException("Event queue specified may not be shut down!");
            }

            this.regularEventQueue = eventQueue;
            this.regularEventQueue.Subscribers.Add <ShuttingDownEvent>(this, weakRef: false);
            this.currentAppState = new ThreadSafeEnum <AppState>(AppState.Shutdown);
        }
        /// <summary>
        /// Creates a new, stateless event handler.
        /// </summary>
        /// <typeparam name="TEvent">The type of events to handle instances of. The actual type of those instances may be a subclass of <typeparamref name="TEvent"/>.</typeparam>
        /// <param name="handler">The event handler delegate to use.</param>
        /// <returns>A new event handler instance.</returns>
        public static IEventHandler <TEvent> On <TEvent>(Action <TEvent> handler)
            where TEvent : EventBase
        {
            if (handler.NullReference())
            {
                throw Exc.Null(nameof(handler));
            }

            return(On <TEvent, object>(
                       (currentState, evnt) =>
            {
                handler(evnt);
                return null;
            },
                       initialState: null));
        }
        internal static EventSubscriberTypeInfo AddOrGet(Type subscriberType)
        {
            if (subscriberType.NullReference())
            {
                throw Exc.Null(nameof(subscriberType));
            }

            lock ( syncLock )
            {
                if (!subscriberInfos.TryGetValue(subscriberType, out var info))
                {
                    info = new EventSubscriberTypeInfo(subscriberType);
                    subscriberInfos.Add(subscriberType, info);
                }
                return(info);
            }
        }
            internal DirectPropertyChangedListener(
                string property,
                Func <TSource, TProperty> getProperty,
                IEqualityComparer <TProperty> propertyComparer)
            {
                if (property.NullReference())
                {
                    throw Exc.Null("Invalid property name: null!");
                }

                if (string.IsNullOrWhiteSpace(property) ||
                    char.IsWhiteSpace(property[0]) ||
                    char.IsWhiteSpace(property[property.Length - 1]))
                {
                    throw new ArgumentException($"Invalid property name: \"{property}\"!");
                }

                this.propertyName     = property;
                this.getPropertyValue = getProperty ?? throw Exc.Null(nameof(getProperty));
                this.comparer         = propertyComparer; // may be null!
                this.source           = default;
                this.lastValue        = default;
            }
Esempio n. 26
0
        /// <summary>
        /// Removes the specified event handler.
        /// Any other event handlers that the <paramref name="eventHandler"/> instance might implement,
        /// which may or may not be registered as well, will be ignored.
        /// </summary>
        /// <typeparam name="TEvent">The type of event to remove a handler of.</typeparam>
        /// <param name="eventHandler">The event handler to remove.</param>
        /// <returns><c>true</c> if the event handler was removed; <c>false</c> if it could not be found.</returns>
        public bool Remove <TEvent>(IEventHandler <TEvent> eventHandler)
            where TEvent : EventBase
        {
            if (eventHandler.NullReference())
            {
                throw Exc.Null(nameof(eventHandler));
            }

            lock (this.subscribers)
            {
                if (this.isClosed)
                {
                    return(false);
                }

                int index = this.IndexOfSpecificEventHandler <TEvent>(eventHandler);
                if (index != -1)
                {
                    this.subscribers.RemoveAt(index);
                    return(true);
                }
                return(false);
            }
        }
 internal ChainChangeNotifier(Action <T, T> action)
 {
     this.notify = action ?? throw Exc.Null(nameof(action));
 }
Esempio n. 28
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DelegateCommand"/> class.
 /// </summary>
 /// <param name="execute">The delegate invoked by Execute.</param>
 /// <param name="canExecute">The delegate invoked by CanExecute.</param>
 public DelegateCommand(Action execute, Func <bool> canExecute = null)
 {
     this.execute    = execute ?? throw Exc.Null(nameof(execute));
     this.canExecute = canExecute;
 }
Esempio n. 29
0
 internal StrongEventHandlerWrapper(IEventHandler <TEvent> subscriber)
 {
     this.strongRef = subscriber ?? throw Exc.Null(nameof(subscriber));
 }
Esempio n. 30
0
 public FinishedEventHandler(IEventQueue eventQueue, int eventIndex, EventHandledDelegate onHandled)
 {
     this.queue   = eventQueue ?? throw Exc.Null(nameof(eventQueue));
     this.index   = eventIndex;
     this.handler = onHandled ?? throw Exc.Null(nameof(onHandled));
 }