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); }
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(); }
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(); }
public void Emit(IEventEmitter sender, IEvent @event, EventExecutedCallback callback = null) { if (!sender.IsAlive) { return; } if (sender == null) { throw new ArgumentNullException(nameof(sender)); } if (@event == null) { throw new ArgumentNullException(nameof(@event)); } string eventNameString = "[" + string.Join(", ", @event.Names.ToArray()) + "]" + " by \"" + sender.Name + "\""; string primaryName = @event.Names.First(); logger?.LogTrace(eventNameString + ": Emitting."); inProgress.Add(@event); List <EventAction> actions = eventListeners .Where(c => c.TargetEventType?.IsInstanceOfType(@event) ?? @event.Names.Any(d => c.TargetEventNames.Any(e => d.Equals(e, StringComparison.OrdinalIgnoreCase))) && c.Owner.IsAlive) .ToList(); actions.Sort((a, b) => ServicePriorityComparer.Compare(a.Handler.Priority, b.Handler.Priority)); List <EventAction> targetActions = (from info in actions /* ignore cancelled events */ where !(@event is ICancellableEvent) || !((ICancellableEvent)@event).IsCancelled || info.Handler.IgnoreCancelled where CheckEmitter(info, sender.Name, @event.IsGlobal) where CheckEvent(info, @event.Names) select info) .ToList(); void FinishEvent() { logger?.LogTrace(eventNameString + ": Finished."); inProgress.Remove(@event); callback?.Invoke(@event); } if (targetActions.Count == 0) { logger?.LogTrace(eventNameString + ": No listeners found."); FinishEvent(); return; } container.TryResolve(null, out ITaskScheduler scheduler); if (scheduler == null && @event.ExecutionTarget != EventExecutionTargetContext.Sync) { FinishEvent(); return; } int executionCount = 0; foreach (EventAction info in targetActions) { ILifecycleObject pl = info.Owner; if (scheduler == null) { info.Action.Invoke(sender, @event); continue; } scheduler.ScheduleUpdate(pl, () => { executionCount++; info.Action.Invoke(sender, @event); //all actions called; run OnEventExecuted if (executionCount == targetActions.Count) { FinishEvent(); } }, primaryName + "EmitTask", (ExecutionTargetContext)@event.ExecutionTarget); } if (scheduler == null) { FinishEvent(); } }
public void Emit(object sender, IEvent @event, EventExecutedCallback callback = null) { if (sender == null) { throw new ArgumentNullException(nameof(sender)); } if (@event == null) { throw new ArgumentNullException(nameof(@event)); } #if LOG_EVENTS string eventNameString = $"{string.Join(", ", @event.Names.Select(d => d + "Event"))}"; logger.LogDebug(eventNameString + " fired."); #endif _inProgress.Add(@event); var names = GetEventNames(@event.GetType()); List <EventAction> actions = _eventListeners .Where(c => c.TargetEventType?.IsInstanceOfType(@event) ?? names.Any(d => c.TargetEventNames.Any(e => d.Equals(e, StringComparison.OrdinalIgnoreCase)))) .ToList(); actions.Sort((a, b) => EventPriorityComparer.Compare(a.Handler.Priority, b.Handler.Priority)); List <EventAction> targetActions = (from info in actions /* ignore cancelled events */ where !(@event is ICancellableEvent) || !((ICancellableEvent)@event).IsCancelled || info.Handler.IgnoreCancelled where CheckEvent(info, names) select info) .ToList(); void FinishEvent() { _inProgress.Remove(@event); callback?.Invoke(@event); } if (targetActions.Count == 0) { #if LOG_EVENTS logger.LogDebug(eventNameString + ": No listeners found."); #endif FinishEvent(); return; } foreach (EventAction info in targetActions) { var wk = info.Owner; //check if owner is alive if (!wk.TryGetTarget(out object _)) { actions.RemoveAll(c => c.Owner == wk); } info.Action.Invoke(sender, @event); } FinishEvent(); }