public HandlerAndWrapper(object eventHandler, Type eventType, BeforeDuringOrAfter beforeDuringOrAfter, bool isAsync) { EventHandler = eventHandler; IsAsync = isAsync; switch (beforeDuringOrAfter, isAsync) {
/// <summary> /// This finds either sync or async handlers for the event and runs the handlers with the input event /// </summary> /// <param name="entityAndEvent"></param> /// <param name="loopCount">This gives the loop number for the RunBefore/AfterSaveChangesEvents</param> /// <param name="beforeDuringOrAfter">tells you what type of event to find/Run</param> /// <param name="allowAsync">true if async is allowed</param> /// <returns>Returns a Task containing the combined status from all the event handlers that ran</returns> public async ValueTask <IStatusGeneric> RunHandlersForEventAsync(EntityAndEvent entityAndEvent, int loopCount, BeforeDuringOrAfter beforeDuringOrAfter, bool allowAsync) { var status = new StatusGenericHandler { Message = "Successfully saved." }; var handlersAndWrappers = _findHandlers.GetHandlers(entityAndEvent, beforeDuringOrAfter, allowAsync); foreach (var handlerWrapper in handlersAndWrappers) { LogEventHandlerRun(loopCount, beforeDuringOrAfter, handlerWrapper); if (beforeDuringOrAfter == BeforeDuringOrAfter.BeforeSave) { var handlerStatus = handlerWrapper.IsAsync ? await((BeforeSaveEventHandlerAsync)Activator.CreateInstance(handlerWrapper.WrapperType, handlerWrapper.EventHandler)) .HandleAsync(entityAndEvent.CallingEntity, entityAndEvent.EntityEvent).ConfigureAwait(false) : ((BeforeSaveEventHandler)Activator.CreateInstance(handlerWrapper.WrapperType, handlerWrapper.EventHandler)) .Handle(entityAndEvent.CallingEntity, entityAndEvent.EntityEvent); if (handlerStatus != null) { status.CombineStatuses(handlerStatus); } } else if (beforeDuringOrAfter == BeforeDuringOrAfter.AfterSave) { if (handlerWrapper.IsAsync) { await((AfterSaveEventHandlerAsync)Activator.CreateInstance(handlerWrapper.WrapperType, handlerWrapper.EventHandler)) .HandleAsync(entityAndEvent.CallingEntity, entityAndEvent.EntityEvent).ConfigureAwait(false); } else { ((AfterSaveEventHandler)Activator.CreateInstance(handlerWrapper.WrapperType, handlerWrapper.EventHandler)) .Handle(entityAndEvent.CallingEntity, entityAndEvent.EntityEvent); } } else { //Its either of the during events var handlerStatus = handlerWrapper.IsAsync ? await((DuringSaveEventHandlerAsync)Activator.CreateInstance(handlerWrapper.WrapperType, handlerWrapper.EventHandler)) .HandleAsync(entityAndEvent.CallingEntity, entityAndEvent.EntityEvent, _uniqueValue) .ConfigureAwait(false) : ((DuringSaveEventHandler)Activator.CreateInstance(handlerWrapper.WrapperType, handlerWrapper.EventHandler)) .Handle(entityAndEvent.CallingEntity, entityAndEvent.EntityEvent, _uniqueValue); if (handlerStatus != null) { status.CombineStatuses(handlerStatus); } } } return(status); }
public List <HandlerAndWrapper> GetHandlers(EntityAndEvent entityAndEvent, BeforeDuringOrAfter beforeDuringOrAfter, bool lookForAsyncHandlers) { var eventType = entityAndEvent.EntityEvent.GetType(); var asyncHandlers = new List <object>(); List <object> GetAsyncHandlers() { var asyncHandlerInterface = GetEventHandlerGenericType(beforeDuringOrAfter, true) .MakeGenericType(eventType); asyncHandlers = _serviceProvider.GetServices(asyncHandlerInterface).ToList(); return(asyncHandlers); } if (lookForAsyncHandlers) { asyncHandlers = GetAsyncHandlers(); } var syncHandlerInterface = GetEventHandlerGenericType(beforeDuringOrAfter, false) .MakeGenericType(eventType); var syncHandler = _serviceProvider.GetServices(syncHandlerInterface) //This removes sync event handlers that have the same name .Where(x => asyncHandlers.All(y => !string.Equals(x.GetType().Name + "Async", y.GetType().Name, StringComparison.InvariantCultureIgnoreCase))) .ToList(); var result = asyncHandlers.Select(x => new HandlerAndWrapper(x, eventType, beforeDuringOrAfter, true)) .Union(syncHandler.Select(x => new HandlerAndWrapper(x, eventType, beforeDuringOrAfter, false))).ToList(); if (!result.Any()) { var suffix = GetAsyncHandlers().Any() ? " Their was a suitable async event handler available, but you didn't call SaveChangesAsync." : ""; _logger.LogError($"Missing handler for event of type {eventType.FullName} for {beforeDuringOrAfter} event handler.{suffix}"); throw new GenericEventRunnerException( $"Could not find a {beforeDuringOrAfter} event handler for the event {eventType.Name}.{suffix}", entityAndEvent.CallingEntity, entityAndEvent.EntityEvent); } return(result); }
private Type GetEventHandlerGenericType(BeforeDuringOrAfter beforeDuringOrAfter, bool lookForAsyncHandlers) { switch (beforeDuringOrAfter, lookForAsyncHandlers) {
private void LogEventHandlerRun(int loopCount, BeforeDuringOrAfter beforeDuringOrAfter, HandlerAndWrapper handlerWrapper) { _logger.LogInformation( $"{beforeDuringOrAfter.ToString()[0]}{loopCount}: About to run a {beforeDuringOrAfter} event handler {handlerWrapper.EventHandler.GetType().FullName}."); }