/// <summary> /// Executes the specified this action on the specified target. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The node.</param> /// <param name="context">The context.</param> public override void Execute(ActionMessage actionMessage, IInteractionNode handlingNode, object context) { try { TryUpdateTrigger(actionMessage, handlingNode, true); var parameters = _messageBinder.DetermineParameters( actionMessage, _requirements, handlingNode, context ); var beforeProcessors = _filters.PreProcessors.OfType<IBeforeProcessor>(); foreach (var filter in _filters.PreProcessors.Except(beforeProcessors.Cast<IPreProcessor>())) { if (!filter.Execute(actionMessage, handlingNode, parameters)) return; } //Before foreach (var before in beforeProcessors.OrderByDescending(p => p.Priority)) { if (!before.BeforeExecute(actionMessage, handlingNode, parameters)) return; } CurrentBackgroundActionInfo = _filters.PostProcessors.OfType<IBackgroundActionInfo>().Single(); var container = handlingNode.MessageHandler.Unwrap() as IExtendedPresenter; CurrentBackgroundTask = container.GetMetadata<IBackgroundThreadTask>(); if (CurrentBackgroundTask == null) { CurrentBackgroundTask = TaskImplFactory.CreateTask(CurrentBackgroundActionInfo.TaskMode); container.WasShutdown += (s, e) => CurrentBackgroundTask.Dispose(); container.AddMetadata(CurrentBackgroundTask); AttachTaskEvents(actionMessage, handlingNode, parameters); } //Exectue Before method if (CurrentBackgroundActionInfo.BeforeMethod != null) { var result = CurrentBackgroundActionInfo.BeforeMethod.Invoke(container, parameters); bool canProceed = true; if (CurrentBackgroundActionInfo.BeforeMethod.Info.ReturnType == typeof(bool)) canProceed = result.As<bool>(); if (!canProceed) return; } DoExecute(actionMessage, handlingNode, parameters); } catch (Exception ex) { TryUpdateTrigger(actionMessage, handlingNode, false); if (!TryApplyRescue(actionMessage, handlingNode, ex)) throw; OnCompleted(); } }
/// <summary> /// Executes the specified this action on the specified target. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The node.</param> /// <param name="context">The context.</param> public override void Execute(ActionMessage actionMessage, IInteractionNode handlingNode, object context) { try { TryUpdateTrigger(actionMessage, handlingNode, true); var parameters = _messageBinder.DetermineParameters( actionMessage, _requirements, handlingNode, context ); CurrentTask = _method.CreateBackgroundTask(handlingNode.MessageHandler.Unwrap(), parameters); foreach (var filter in _filters.PreProcessors) { if (filter.Execute(actionMessage, handlingNode, parameters)) continue; TryUpdateTrigger(actionMessage, handlingNode, false); return; } DoExecute(actionMessage, handlingNode, parameters); } catch (Exception ex) { TryUpdateTrigger(actionMessage, handlingNode, false); if(!TryApplyRescue(actionMessage, handlingNode, ex)) throw; OnCompleted(); } }
/// <summary> /// Executes the specified this action on the specified target. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The node.</param> /// <param name="context">The context.</param> public override void Execute(ActionMessage actionMessage, IInteractionNode handlingNode, object context) { try { var parameters = _messageBinder.DetermineParameters( actionMessage, _requirements, handlingNode, context ); TryUpdateTrigger(actionMessage, handlingNode, true); foreach (var filter in _filters.PreProcessors) { if (filter.Execute(actionMessage, handlingNode, parameters)) continue; TryUpdateTrigger(actionMessage, handlingNode, false); return; } var outcome = new MessageProcessingOutcome( _method.Invoke(handlingNode.MessageHandler.Unwrap(), parameters), _method.Info.ReturnType, false ); foreach (var filter in _filters.PostProcessors) { filter.Execute(actionMessage, handlingNode, outcome); } HandleOutcome(actionMessage, handlingNode, outcome); } catch (Exception ex) { TryUpdateTrigger(actionMessage, handlingNode, false); if(!TryApplyRescue(actionMessage, handlingNode, ex)) { Log.Error(ex); throw; } OnCompleted(); } }
public override void Execute(ActionMessage actionMessage, IInteractionNode handlingNode, object context) { try { var parameters = _messageBinder.DetermineParameters(actionMessage,_requirements,handlingNode,context); // IBeforeProcessor 继承 IPreProcessor 相当于一样 var processors = _filters.PreProcessors.OfType<IBeforeProcessor>(); // caliburn preProcessor (before) (针对 IBeforeProcessor) foreach (var filter in _filters.PreProcessors.Except(processors.Cast<IPreProcessor>())) { if (!filter.Execute(actionMessage, handlingNode, parameters)) return; } // before custom aop hehavior (针对IPreProcessor) foreach (var before in processors.OrderByDescending(p => p.Priority)) { if (!before.BeforeExecute(actionMessage, handlingNode, parameters)) return; } object result = null; // the method will excute result = _method.Invoke(handlingNode.MessageHandler.Unwrap(), parameters); var outcome = new MessageProcessingOutcome(result ,_method.Info.ReturnType,false); // post foreach (var filter in _filters.PostProcessors) { filter.Execute(actionMessage, handlingNode, outcome); } HandleOutcome(actionMessage, handlingNode, outcome); } catch (Exception ex) { if (!TryApplyRescue(actionMessage, handlingNode, ex)) throw; OnCompleted(); } }
/// <summary> /// Determines how this instance affects trigger availability. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The node.</param> /// <returns> /// <c>true</c> if this instance enables triggers; otherwise, <c>false</c>. /// </returns> public virtual bool ShouldTriggerBeAvailable(ActionMessage actionMessage, IInteractionNode handlingNode) { var parameters = _messageBinder.DetermineParameters( actionMessage, _requirements, handlingNode, null ); foreach (var filter in _filters.TriggerEffects) { if (!filter.Execute(actionMessage, handlingNode, parameters)) { return(false); } } return(true); }
/// <summary> /// Executes the specified this action on the specified target. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The node.</param> /// <param name="context">The context.</param> public override void Execute(ActionMessage actionMessage, IInteractionNode handlingNode, object context) { try { var parameters = _messageBinder.DetermineParameters( actionMessage, _requirements, handlingNode, context ); foreach (var filter in _filters.PreProcessors) { if (!filter.Execute(actionMessage, handlingNode, parameters)) { return; } } var outcome = new MessageProcessingOutcome( _method.Invoke(handlingNode.MessageHandler.Unwrap(), parameters), _method.Info.ReturnType, false ); foreach (var filter in _filters.PostProcessors) { filter.Execute(actionMessage, handlingNode, outcome); } HandleOutcome(actionMessage, handlingNode, outcome); } catch (Exception ex) { if (!TryApplyRescue(actionMessage, handlingNode, ex)) { throw; } OnCompleted(); } }
private void HandleOutcome(ActionMessage message, IInteractionNode handlingNode, MessageProcessingOutcome outcome) { var result = _messageBinder.CreateResult(outcome); result.Completed += (s, e) =>{ TryUpdateTrigger(message, handlingNode, false); if(e.Error != null) { if(!TryApplyRescue(message, handlingNode, e.Error)) { Log.Error(e.Error); throw e.Error; } } OnCompleted(); }; result.Execute(new ResultExecutionContext(serviceLocator, message, handlingNode)); }
private void HandleOutcome(ActionMessage message, IInteractionNode handlingNode, MessageProcessingOutcome outcome) { var result = MessageBinder.CreateResult(outcome); result.Completed += (s, e) => { TryUpdateTrigger(message, handlingNode, false); if (e.Error != null) { if (!TryApplyRescue(message, handlingNode, e.Error)) { Log.Error(e.Error); throw e.Error; } } OnCompleted(); }; result.Execute(new ResultExecutionContext(serviceLocator, message, handlingNode)); }
/// <summary> /// Executes the specified this action on the specified target. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The node.</param> /// <param name="context">The context.</param> public override void Execute(ActionMessage actionMessage, IInteractionNode handlingNode, object context) { try { var parameters = MessageBinder.DetermineParameters( actionMessage, UnderlyingRequirements, handlingNode, context ); TryUpdateTrigger(actionMessage, handlingNode, true); CurrentTask = UnderlyingMethod.CreateBackgroundTask(handlingNode.MessageHandler.Unwrap(), parameters); foreach (var filter in UnderlyingFilters.PreProcessors) { if (filter.Execute(actionMessage, handlingNode, parameters)) { continue; } TryUpdateTrigger(actionMessage, handlingNode, false); return; } DoExecute(actionMessage, handlingNode, parameters); } catch (Exception ex) { TryUpdateTrigger(actionMessage, handlingNode, false); if (!TryApplyRescue(actionMessage, handlingNode, ex)) { Log.Error(ex); throw; } OnCompleted(); } }
/// <summary> /// Determines whether this action matches the specified message. /// </summary> /// <param name="message">The message.</param> /// <returns></returns> public bool Matches(ActionMessage message) { if (UnderlyingRequirements.Count == message.Parameters.Count) { bool isMatch = true; for (int i = 0; i < message.Parameters.Count; i++) { var expectedType = UnderlyingRequirements[i].Type; var value = message.Parameters[i].Value; if (value == null) { if (expectedType.IsClass || expectedType.IsInterface) { continue; } isMatch = false; break; } if (expectedType.IsAssignableFrom(value.GetType())) { continue; } isMatch = false; break; } Log.Info("Action {0} for {1}.", isMatch ? "found" : "not found", this); return(isMatch); } Log.Info("Action not found for {0}.", this); return(false); }
/// <summary> /// Determines the overload or fail. /// </summary> /// <param name="message">The message.</param> /// <returns></returns> public IAction DetermineOverloadOrFail(ActionMessage message) { foreach (var overload in overloads) { if (overload.Matches(message)) { return(overload); } } if (message.Parameters.Count > 0) { var ex = new CaliburnException( string.Format( "Could not find overload for {0}({1}).", message.MethodName, message.Parameters .Select(x => x.Value == null ? "null" : x.Value.GetType().Name) .Aggregate((a, c) => a + ", " + c) ) ); Log.Error(ex); throw ex; } var ex2 = new CaliburnException( string.Format( "Could not find overload for {0}().", message.MethodName ) ); Log.Error(ex2); throw ex2; }
/// <summary> /// Determines whether this action matches the specified message. /// </summary> /// <param name="message">The message.</param> /// <returns></returns> public bool Matches(ActionMessage message) { if (_requirements.Count == message.Parameters.Count) { bool isMatch = true; for (int i = 0; i < message.Parameters.Count; i++) { var expectedType = _requirements[i].Type; var value = message.Parameters[i].Value; if (value == null) { if (expectedType.IsClass || expectedType.IsInterface) { continue; } isMatch = false; break; } if (expectedType.IsAssignableFrom(value.GetType())) { continue; } isMatch = false; break; } return(isMatch); } return(false); }
/// <summary> /// Determines how this instance affects trigger availability. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The node.</param> /// <returns> /// <c>true</c> if this instance enables triggers; otherwise, <c>false</c>. /// </returns> public virtual bool ShouldTriggerBeAvailable(ActionMessage actionMessage, IInteractionNode handlingNode) { if (!HasTriggerEffects()) return true; var parameters = _messageBinder.DetermineParameters( actionMessage, _requirements, handlingNode, null ); Log.Info("Evaluating trigger effects for {0}.", this); foreach (var filter in _filters.TriggerEffects) { if (!filter.Execute(actionMessage, handlingNode, parameters)) return false; } return true; }
IActionHandler FindActionHandler(ActionMessage message) { return(host.GetAction(message) ?? target as IActionHandler); }
/// <summary> /// Attaches the task complete. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The handling node.</param> /// <param name="parameters">The parameters.</param> protected void AttachTaskEvents(ActionMessage actionMessage, IInteractionNode handlingNode, object[] parameters) { if (CurrentBackgroundActionInfo.ShowBusyCursor) { CurrentBackgroundTask.Starting += (s, e) => Caliburn.Core.Invocation.Execute.OnUIThread( () => { FrameworkElement element = handlingNode.UIElement as FrameworkElement; element.Cursor = Cursors.Wait; }); CurrentBackgroundTask.Completed += (s, e) => Caliburn.Core.Invocation.Execute.OnUIThread( () => { FrameworkElement element = handlingNode.UIElement as FrameworkElement; element.Cursor = Cursors.Arrow; }); } CurrentBackgroundTask.Completed += (s, e) => Caliburn.Core.Invocation.Execute.OnUIThread( () => { Interlocked.Decrement(ref _runningCount); if (e.Error != null) { TryUpdateTrigger(actionMessage, handlingNode, false); if (!TryApplyRescue(actionMessage, handlingNode, e.Error)) throw e.Error; OnCompleted(); } else { try { var outcome = new MessageProcessingOutcome( e.Result, _method.Info.ReturnType, e.Cancelled ); foreach (var filter in _filters.PostProcessors) { filter.Execute(actionMessage, handlingNode, outcome); } var result = _messageBinder.CreateResult(outcome); result.Completed += (r, ex) => { TryUpdateTrigger(actionMessage, handlingNode, false); if (ex != null) { if (!TryApplyRescue(actionMessage, handlingNode, ex)) throw ex; } OnCompleted(); }; result.Execute(actionMessage, handlingNode); } catch (Exception ex) { TryUpdateTrigger(actionMessage, handlingNode, false); if (!TryApplyRescue(actionMessage, handlingNode, ex)) throw; OnCompleted(); } } }); Interlocked.Increment(ref _runningCount); }
private IActionHandler FindActionHandler(ActionMessage message) { return _host.GetAction(message) ?? _target as IActionHandler; }
protected void DoExecute(ActionMessage actionMessage, IInteractionNode handlingNode, object[] parameters) { if (CurrentBackgroundActionInfo.BlockIfBusy && CurrentBackgroundTask.IsBusy) return; var context = new BackgroundActionContext(CurrentBackgroundActionInfo.BackgroundEndMode, () => _method.Invoke(handlingNode.MessageHandler.Unwrap(), parameters)); CurrentBackgroundTask.Enqueue(context); }
/// <summary> /// Executes the specified this action on the specified target. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The node.</param> /// <param name="context">The context.</param> public abstract void Execute(ActionMessage actionMessage, IInteractionNode handlingNode, object context);
/// <summary> /// Determines how this instance affects trigger availability. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The node.</param> /// <returns> /// <c>true</c> if this instance enables triggers; otherwise, <c>false</c>. /// </returns> public override bool ShouldTriggerBeAvailable(ActionMessage actionMessage, IInteractionNode handlingNode) { if (BlockInteraction && runningCount > 1) return false; return base.ShouldTriggerBeAvailable(actionMessage, handlingNode); }
/// <summary> /// Executes the core logic, specific to the action type. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The node.</param> /// <param name="parameters">The parameters.</param> protected void DoExecute(ActionMessage actionMessage, IInteractionNode handlingNode, object[] parameters) { CurrentTask.Completed += (s, e) => Invocation.Execute.OnUIThread( () =>{ Interlocked.Decrement(ref runningCount); if(e.Error != null) { TryUpdateTrigger(actionMessage, handlingNode, false); if(!TryApplyRescue(actionMessage, handlingNode, e.Error)) { Log.Error(e.Error); throw e.Error; } OnCompleted(); } else { try { var outcome = new MessageProcessingOutcome( e.Cancelled ? null : e.Result, _method.Info.ReturnType, e.Cancelled ); foreach(var filter in _filters.PostProcessors) { filter.Execute(actionMessage, handlingNode, outcome); } var result = _messageBinder.CreateResult(outcome); result.Completed += (r, arg) =>{ TryUpdateTrigger(actionMessage, handlingNode, false); if(arg.Error != null) { if(!TryApplyRescue(actionMessage, handlingNode, arg.Error)) { Log.Error(arg.Error); throw arg.Error; } } OnCompleted(); }; result.Execute(new ResultExecutionContext(serviceLocator, actionMessage, handlingNode)); } catch(Exception ex) { TryUpdateTrigger(actionMessage, handlingNode, false); if(!TryApplyRescue(actionMessage, handlingNode, ex)) { Log.Error(ex); throw; } OnCompleted(); } } }); Interlocked.Increment(ref runningCount); CurrentTask.Start(this); CurrentTask = null; }
/// <summary> /// Tries to update trigger. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The handling node.</param> /// <param name="forceDisabled">if set to <c>true</c> [force disabled].</param> protected virtual void TryUpdateTrigger(ActionMessage actionMessage, IInteractionNode handlingNode, bool forceDisabled) { if (!BlockInteraction) return; Log.Info("Updating trigger for {0}.", this); foreach (var messageTrigger in actionMessage.Source.Triggers) { if (!messageTrigger.Message.Equals(actionMessage)) continue; if (forceDisabled) { messageTrigger.UpdateAvailabilty(false); return; } bool isAvailable = ShouldTriggerBeAvailable(actionMessage, handlingNode); messageTrigger.UpdateAvailabilty(isAvailable); return; } }
/// <summary> /// Gets the action. /// </summary> /// <param name="message">The action message.</param> /// <returns></returns> public IAction GetAction(ActionMessage message) { IAction found; _actions.TryGetValue(message.MethodName, out found); return found; }
/// <summary> /// Executes the core logic, specific to the action type. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The node.</param> /// <param name="parameters">The parameters.</param> protected void DoExecute(ActionMessage actionMessage, IInteractionNode handlingNode, object[] parameters) { CurrentTask.Completed += (s, e) => Invocation.Execute.OnUIThread( () => { Interlocked.Decrement(ref runningCount); if (e.Error != null) { TryUpdateTrigger(actionMessage, handlingNode, false); if (!TryApplyRescue(actionMessage, handlingNode, e.Error)) { Log.Error(e.Error); throw e.Error; } OnCompleted(); } else { try { var outcome = new MessageProcessingOutcome( e.Cancelled ? null : e.Result, UnderlyingMethod.Info.ReturnType, e.Cancelled ); foreach (var filter in UnderlyingFilters.PostProcessors) { filter.Execute(actionMessage, handlingNode, outcome); } var result = MessageBinder.CreateResult(outcome); result.Completed += (r, arg) => { TryUpdateTrigger(actionMessage, handlingNode, false); if (arg.Error != null) { if (!TryApplyRescue(actionMessage, handlingNode, arg.Error)) { Log.Error(arg.Error); throw arg.Error; } } OnCompleted(); }; result.Execute(new ResultExecutionContext(serviceLocator, actionMessage, handlingNode)); } catch (Exception ex) { TryUpdateTrigger(actionMessage, handlingNode, false); if (!TryApplyRescue(actionMessage, handlingNode, ex)) { Log.Error(ex); throw; } OnCompleted(); } } }); Interlocked.Increment(ref runningCount); CurrentTask.Start(this); CurrentTask = null; }
/// <summary> /// Determines how this instance affects trigger availability. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The node.</param> /// <returns> /// <c>true</c> if this instance enables triggers; otherwise, <c>false</c>. /// </returns> public bool ShouldTriggerBeAvailable(ActionMessage actionMessage, IInteractionNode handlingNode) { return(DetermineOverloadOrFail(actionMessage).ShouldTriggerBeAvailable(actionMessage, handlingNode)); }
/// <summary> /// Tries to update trigger. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The handling node.</param> /// <param name="forceDisabled">if set to <c>true</c> [force disabled].</param> protected virtual void TryUpdateTrigger(ActionMessage actionMessage, IInteractionNode handlingNode, bool forceDisabled) { if (!BlockInteraction) return; foreach (var messageTrigger in actionMessage.Source.Triggers) { if (!messageTrigger.Message.Equals(actionMessage)) continue; if (forceDisabled) { messageTrigger.UpdateAvailabilty(false); return; } if (this.HasTriggerEffects()) { bool isAvailable = ShouldTriggerBeAvailable(actionMessage, handlingNode); messageTrigger.UpdateAvailabilty(isAvailable); } else messageTrigger.UpdateAvailabilty(true); return; } }
/// <summary> /// Executes the core logic, specific to the action type. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The node.</param> /// <param name="parameters">The parameters.</param> protected void DoExecute(ActionMessage actionMessage, IInteractionNode handlingNode, object[] parameters) { CurrentTask.Completed += (s, e) => Core.Invocation.Execute.OnUIThread( () => { Interlocked.Decrement(ref _runningCount); if (e.Error != null) { TryUpdateTrigger(actionMessage, handlingNode, false); if (!TryApplyRescue(actionMessage, handlingNode, e.Error)) { throw e.Error; } OnCompleted(); } else { try { var outcome = new MessageProcessingOutcome( e.Result, _method.Info.ReturnType, e.Cancelled ); foreach (var filter in _filters.PostProcessors) { filter.Execute(actionMessage, handlingNode, outcome); } var result = _messageBinder.CreateResult(outcome); result.Completed += (r, ex) => { TryUpdateTrigger(actionMessage, handlingNode, false); if (ex != null) { if (!TryApplyRescue(actionMessage, handlingNode, ex)) { throw ex; } } OnCompleted(); }; result.Execute(actionMessage, handlingNode); } catch (Exception ex) { TryUpdateTrigger(actionMessage, handlingNode, false); if (!TryApplyRescue(actionMessage, handlingNode, ex)) { throw; } OnCompleted(); } } }); Interlocked.Increment(ref _runningCount); CurrentTask.Enqueue(this); CurrentTask = null; }
/// <summary> /// Executes the specified this action on the specified target. /// </summary> /// <param name="actionMessage">The action message.</param> /// <param name="handlingNode">The node.</param> /// <param name="context">The context.</param> public void Execute(ActionMessage actionMessage, IInteractionNode handlingNode, object context) { DetermineOverloadOrFail(actionMessage).Execute(actionMessage, handlingNode, context); }
/// <summary> /// Determines whether this action matches the specified message. /// </summary> /// <param name="message">The message.</param> /// <returns></returns> public bool Matches(ActionMessage message) { if (_requirements.Count == message.Parameters.Count) { bool isMatch = true; for (int i = 0; i < message.Parameters.Count; i++) { var expectedType = _requirements[i].Type; var value = message.Parameters[i].Value; if (value == null) { if (expectedType.IsClass || expectedType.IsInterface) continue; isMatch = false; break; } if (expectedType.IsAssignableFrom(value.GetType())) continue; isMatch = false; break; } Log.Info("Action {0} for {1}.", isMatch ? "found" : "not found", this); return isMatch; } Log.Info("Action not found for {0}.", this); return false; }