Пример #1
0
        public void AddPermissionCheckProvider(Type type)
        {
            if (!typeof(IPermissionCheckProvider).IsAssignableFrom(type))
            {
                throw new Exception($"Type {type} must be an instance of IPermissionCheckProvider!");
            }

            if (m_PermissionCheckProviderTypes.Contains(type))
            {
                return;
            }

            m_PermissionCheckProviderTypes.Add(type);
            m_PermissionCheckProviderTypes.Sort((a, b) => m_PriorityComparer.Compare(a.GetPriority(), b.GetPriority()));
        }
Пример #2
0
        public async Task <IReadOnlyCollection <ICommandRegistration> > GetCommandsAsync()
        {
            if (m_IsDisposing)
            {
                throw new ObjectDisposedException(nameof(CommandStore));
            }

            var commands = new List <ICommandRegistration>();

            foreach (var sources in m_CommandSources)
            {
                foreach (var command in await sources.GetCommandsAsync())
                {
                    if (!command.Component.IsComponentAlive)
                    {
                        continue;
                    }

                    var commandData = await GetOrCreateCommandData(command);

                    commands.Add(new RegisteredCommand(command, commandData));
                }
            }

            commands.Sort((a, b) => m_Comparer.Compare(a.Priority, b.Priority));
            return(commands);
        }
Пример #3
0
        public virtual async Task EmitAsync(IOpenModComponent component, object sender, IEvent @event, EventExecutedCallback callback = null)
        {
            if (!component.IsComponentAlive)
            {
                return;
            }

            m_Logger.LogTrace($"Emitting event: {@event.Name}");
            var eventSubscriptions
                = m_EventSubscriptions
                  .Where(c => (c.EventType != null && c.EventType.IsInstanceOfType(@event)) ||
                         (@event.Name.Equals(c.EventName, StringComparison.OrdinalIgnoreCase) &&
                          c.Owner.IsAlive && ((IOpenModComponent)c.Owner.Target).IsComponentAlive))
                  .ToList();


            void Complete()
            {
                m_Logger.LogTrace($"{@event.Name}: Finished.");
                callback?.Invoke(@event);
            }

            if (eventSubscriptions.Count == 0)
            {
                m_Logger?.LogTrace($"{@event.Name}: No listeners found.");
                Complete();
                return;
            }

            var comparer = new PriorityComparer(PriortyComparisonMode.LowestFirst);

            eventSubscriptions.Sort((a, b) => comparer.Compare(a.EventListenerAttribute.Priority, b.EventListenerAttribute.Priority));

            foreach (var group in eventSubscriptions.GroupBy(e => e.Scope))
            {
                await using var newScope = group.Key.BeginLifetimeScope("AutofacWebRequest");
                foreach (var subscription in group)
                {
                    if (@event is ICancellableEvent cancellableEvent &&
                        cancellableEvent.IsCancelled &&
                        !subscription.EventListenerAttribute.IgnoreCancelled)
                    {
                        continue;
                    }

                    var serviceProvider = newScope.Resolve <IServiceProvider>();

                    try
                    {
                        await subscription.Callback.Invoke(serviceProvider, sender, @event);
                    }
                    catch (Exception ex)
                    {
                        m_Logger.LogError(ex, $"Exception occured during event {@event.Name}");
                    }
                }
            }

            Complete();
        }
Пример #4
0
        public void Should_return_0_for_other_case()
        {
            // Arrange
            var comparer = new PriorityComparer <GenericPriorityMessage <int> >();
            var m1       = new GenericPriorityMessage <int>(1, 0);
            var m2       = new GenericPriorityMessage <int>(1, 0);

            // Action & Assert
            Assert.AreEqual(0, comparer.Compare(m2, m1));
        }
Пример #5
0
        public void Should_return_minus_1_if_object_on_the_left_has_lower_priority_value()
        {
            // Arrange
            var comparer = new PriorityComparer <GenericPriorityMessage <int> >();
            var m1       = new GenericPriorityMessage <int>(1, 10);
            var m2       = new GenericPriorityMessage <int>(1, 0);

            // Action & Assert
            Assert.AreEqual(-1, comparer.Compare(m2, m1));
        }
Пример #6
0
        public void Should_return_0_for_other_case()
        {
            // Arrange
            var comparer = new PriorityComparer<GenericPriorityMessage<int>>();
            var m1 = new GenericPriorityMessage<int>(1, 0);
            var m2 = new GenericPriorityMessage<int>(1, 0);

            // Action & Assert
            Assert.AreEqual(0, comparer.Compare(m2, m1));
        }
Пример #7
0
        public void Should_return_minus_1_if_object_on_the_left_has_lower_priority_value()
        {
            // Arrange
            var comparer = new PriorityComparer<GenericPriorityMessage<int>>();
            var m1 = new GenericPriorityMessage<int>(1, 10);
            var m2 = new GenericPriorityMessage<int>(1, 0);

            // Action & Assert
            Assert.AreEqual(-1, comparer.Compare(m2, m1));
        }
Пример #8
0
        public virtual async Task EmitAsync(IOpenModComponent component, object sender, IEvent @event, EventExecutedCallback callback = null)
        {
            if (!component.IsComponentAlive)
            {
                return;
            }

            m_Logger.LogTrace($"Emitting event: {@event.Name}");
            var eventSubscriptions
                = m_EventSubscriptions
                  .Where(c => (c.EventType != null && c.EventType.IsInstanceOfType(@event)) ||
                         (@event.Name.Equals(c.EventName, StringComparison.OrdinalIgnoreCase) &&
                          c.Owner.IsAlive && ((IOpenModComponent)c.Owner.Target).IsComponentAlive))
                  .ToList();


            void Complete()
            {
                m_Logger.LogTrace($"{@event.Name}: Finished.");
                callback?.Invoke(@event);
            }

            if (eventSubscriptions.Count == 0)
            {
                m_Logger?.LogTrace($"{@event.Name}: No listeners found.");
                Complete();
                return;
            }

            var comparer = new PriorityComparer(PriortyComparisonMode.LowestFirst);

            eventSubscriptions.Sort((a, b) => comparer.Compare(a.EventListenerAttribute.Priority, b.EventListenerAttribute.Priority));

            foreach (var subscription in eventSubscriptions)
            {
                var owner = subscription.Owner;
                if (!owner.IsAlive || !((IOpenModComponent)owner.Target).IsComponentAlive)
                {
                    m_EventSubscriptions.Remove(subscription);
                    continue;
                }

                if (@event is ICancellableEvent cancellableEvent &&
                    cancellableEvent.IsCancelled &&
                    !subscription.EventListenerAttribute.IgnoreCancelled)
                {
                    continue;
                }

                var serviceProvider = subscription.Scope.Resolve <IServiceProvider>();
                await subscription.Callback.Invoke(serviceProvider, sender, @event);
            }

            Complete();
        }
Пример #9
0
        public void Should_return_minus_1_if_object_on_the_left_is_younger_than_the_other_one()
        {
            // Arrange
            var comparer = new PriorityComparer<GenericPriorityMessage<int>>();
            var m1 = new GenericPriorityMessage<int>(1, 0);
            System.Threading.Thread.Sleep(1);
            var m2 = new GenericPriorityMessage<int>(1, 0);

            // Action & Assert
            Assert.AreEqual(-1, comparer.Compare(m2, m1));
        }
Пример #10
0
        public void Should_return_minus_1_if_object_on_the_left_is_younger_than_the_other_one()
        {
            // Arrange
            var comparer = new PriorityComparer <GenericPriorityMessage <int> >();
            var m1       = new GenericPriorityMessage <int>(1, 0);

            System.Threading.Thread.Sleep(1);
            var m2 = new GenericPriorityMessage <int>(1, 0);

            // Action & Assert
            Assert.AreEqual(-1, comparer.Compare(m2, m1));
        }
Пример #11
0
        public void AddJobExecutor(Type type)
        {
            if (!typeof(ITaskExecutor).IsAssignableFrom(type))
            {
                throw new Exception($"Type {type} must be an instance of IJobExecutor!");
            }

            if (m_JobExecutorTypes.Contains(type))
            {
                return;
            }

            m_JobExecutorTypes.Add(type);
            m_JobExecutorTypes.Sort((a, b) => m_PriorityComparer.Compare(a.GetPriority(), b.GetPriority()));
        }
Пример #12
0
        public void AddCommandSource(Type type)
        {
            if (!typeof(ICommandSource).IsAssignableFrom(type))
            {
                throw new Exception($"Type {type} must be an instance of ICommandSource!");
            }

            if (m_CommandSourceTypes.Contains(type))
            {
                return;
            }

            m_CommandSourceTypes.Add(type);
            m_CommandSourceTypes.Sort((a, b) => m_PriorityComparer.Compare(a.GetPriority(), b.GetPriority()));
        }
Пример #13
0
        public void AddCommandParameterResolveProvider(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (!typeof(ICommandParameterResolveProvider).IsAssignableFrom(type))
            {
                throw new ArgumentException($"Type {type} must be an instance of {nameof(ICommandParameterResolveProvider)}!", nameof(type));
            }

            if (m_CommandParameterResolveProviderTypes.Contains(type))
            {
                return;
            }

            m_CommandParameterResolveProviderTypes.Add(type);
            m_CommandParameterResolveProviderTypes.Sort((a, b) => m_PriorityComparer.Compare(a.GetPriority(), b.GetPriority()));
        }
Пример #14
0
        public virtual async Task EmitAsync(IOpenModComponent component, object sender, IEvent @event,
                                            EventExecutedCallback callback = null)
        {
            if (!component.IsComponentAlive)
            {
                return;
            }

            var eventTypes = new List <Type>();

            var currentType = @event.GetType();

            while (currentType != null && typeof(IEvent).IsAssignableFrom(currentType))
            {
                eventTypes.Add(currentType);
                currentType = currentType.BaseType;
            }

            eventTypes.AddRange(@event.GetType().GetInterfaces().Where(d => typeof(IEvent).IsAssignableFrom(d)));

            foreach (var eventType in eventTypes.Except(s_OmittedTypes))
            {
                string eventName = GetEventName(eventType);

                m_Logger.LogTrace($"Emitting event: {eventName}");
                var eventSubscriptions
                    = m_EventSubscriptions
                      .Where(c => (c.EventType != null && c.EventType == eventType) ||
                             (eventName.Equals(c.EventName, StringComparison.OrdinalIgnoreCase) &&
                              c.Owner.IsAlive && ((IOpenModComponent)c.Owner.Target).IsComponentAlive))
                      .ToList();


                if (eventSubscriptions.Count == 0)
                {
                    continue;
                }

                var comparer = new PriorityComparer(PriortyComparisonMode.LowestFirst);
                eventSubscriptions.Sort((a, b) =>
                                        comparer.Compare(
                                            (Priority)a.EventListenerAttribute.Priority,
                                            (Priority)b.EventListenerAttribute.Priority)
                                        );

                foreach (var group in eventSubscriptions.GroupBy(e => e.Scope))
                {
                    await using var newScope = group.Key.BeginLifetimeScope("AutofacWebRequest");
                    foreach (var subscription in group)
                    {
                        var cancellableEvent = @event as ICancellableEvent;

                        if (cancellableEvent != null &&
                            cancellableEvent.IsCancelled &&
                            !subscription.EventListenerAttribute.IgnoreCancelled)
                        {
                            continue;
                        }

                        var wasCancelled = false;
                        if (cancellableEvent != null)
                        {
                            wasCancelled = cancellableEvent.IsCancelled;
                        }

                        var serviceProvider = newScope.Resolve <IServiceProvider>();

                        try
                        {
                            await subscription.Callback.Invoke(serviceProvider, sender, @event);

                            if (cancellableEvent != null && subscription.EventListenerAttribute.Priority ==
                                EventListenerPriority.Monitor)
                            {
                                if (cancellableEvent.IsCancelled != wasCancelled)
                                {
                                    cancellableEvent.IsCancelled = wasCancelled;
                                    m_Logger.LogWarning(
                                        $"{((IOpenModComponent)@subscription.Owner.Target).OpenModComponentId} changed {@eventName} cancellation status with Monitor priority which is not permitted.");
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            m_Logger.LogError(ex, $"Exception occured during event {@eventName}");
                        }
                    }
                }

                m_Logger.LogTrace($"{eventName}: Finished.");
            }

            callback?.Invoke(@event);
        }
Пример #15
0
        public virtual async Task EmitAsync(IOpenModComponent component, object?sender, IEvent @event,
                                            EventExecutedCallback?callback = null)
        {
            if (component == null)
            {
                throw new ArgumentNullException(nameof(component));
            }

            if (@event == null)
            {
                throw new ArgumentNullException(nameof(@event));
            }

            if (!component.IsComponentAlive)
            {
                m_Logger.LogDebug($"EmitAsync called by {component.OpenModComponentId} for {@event.GetType().Name} but the component is not alive.");
                return;
            }

            var eventTypes  = new List <Type>();
            var currentType = @event.GetType();

            while (currentType != null && typeof(IEvent).IsAssignableFrom(currentType))
            {
                eventTypes.Add(currentType);
                currentType = currentType.BaseType;
            }

            eventTypes.AddRange(@event.GetType().GetInterfaces().Where(d => typeof(IEvent).IsAssignableFrom(d)));

            foreach (var eventType in eventTypes.Except(s_OmittedTypes))
            {
                string eventName = GetEventName(eventType);

                m_Logger.LogTrace($"Emitting event: {eventName}");
                var eventSubscriptions
                    = m_EventSubscriptions
                      .Where(c => (c.EventType != null && c.EventType == eventType) ||
                             (eventName.Equals(c.EventName, StringComparison.OrdinalIgnoreCase) &&
                              c.Owner.IsAlive && ((IOpenModComponent)c.Owner.Target).IsComponentAlive))
                      .ToList();


                if (eventSubscriptions.Count == 0)
                {
                    m_Logger.LogTrace($"No event subscriptions found for: {eventName}");
                    continue;
                }

                var comparer = new PriorityComparer(PriortyComparisonMode.LowestFirst);
                eventSubscriptions.Sort((a, b) =>
                                        comparer.Compare(
                                            (Priority)a.EventListenerAttribute.Priority,
                                            (Priority)b.EventListenerAttribute.Priority)
                                        );

                foreach (var group in eventSubscriptions.GroupBy(e => e.Scope))
                {
                    //   Creates a new scope for the event. This is needed for scoped services so they share the same service instance
                    // on each events. AutofacWebRequest makes it emulate a request for proper scopes. This tag is hardcoded by AutoFac.
                    // Without this tag, services with the "Scope" lifetime will cause "DependencyResolutionException:
                    // No scope with a Tag matching 'AutofacWebRequest' (...)".
                    //
                    //   If you are here because of the following error:  "System.ObjectDisposedException: Instances cannot
                    // be resolved and nested lifetimes cannot be created from this LifetimeScope as it (or one of its parent scopes)
                    // has already been disposed." It means you injected a service to an IEventHandler
                    // that used the service *after* the event has finished (e.g. in a Task or by storing it somewhere).

                    await using var newScope = group.Key.BeginLifetimeScopeEx("AutofacWebRequest");
                    foreach (var subscription in group)
                    {
                        var cancellableEvent = @event as ICancellableEvent;

                        if (cancellableEvent != null &&
                            cancellableEvent.IsCancelled &&
                            !subscription.EventListenerAttribute.IgnoreCancelled)
                        {
                            continue;
                        }

                        var wasCancelled = false;
                        if (cancellableEvent != null)
                        {
                            wasCancelled = cancellableEvent.IsCancelled;
                        }

                        var serviceProvider = newScope.Resolve <IServiceProvider>();

                        try
                        {
                            await subscription.Callback.Invoke(serviceProvider, sender, @event);

                            // Ensure monitor event listeners can't cancel or uncancel events
                            if (cancellableEvent != null && subscription.EventListenerAttribute.Priority ==
                                EventListenerPriority.Monitor)
                            {
                                if (cancellableEvent.IsCancelled != wasCancelled)
                                {
                                    cancellableEvent.IsCancelled = wasCancelled;
                                    m_Logger.LogWarning(
                                        $"{((IOpenModComponent)@subscription.Owner.Target).OpenModComponentId} changed {@eventName} cancellation status with Monitor priority which is not permitted.");
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            m_Logger.LogError(ex, $"Exception occured during event {@eventName}");
                        }
                    }
                }

                m_Logger.LogTrace($"{eventName}: Finished.");
            }

            callback?.Invoke(@event);
        }