/// <summary> /// Ends an action using the specified <see cref="ActionRunInfo"/> instance. /// </summary> /// <param name="actionRunInfo">The run info about the action.</param> private static void EndAction(ActionRunInfo actionRunInfo) { if (actionRunInfo.SharedState.CurrentActionId != actionRunInfo.ActionId) { throw new InvalidOperationException(Resources.InvalidActionStack); } actionRunInfo.SharedState.CurrentActionId = actionRunInfo.ParentActionId; if (actionRunInfo.Exception != null) { actionRunInfo.SharedState.SuppressReactionErrors = true; } actionRunInfo.SharedState.EndAllowStateChanges(actionRunInfo.PreviousAllowStateChanges); actionRunInfo.SharedState.EndAllowStateReads(actionRunInfo.PreviousAllowStateReads); actionRunInfo.SharedState.EndBatch(); actionRunInfo.SharedState.EndTracking(actionRunInfo.PreviousDerivation); if (actionRunInfo.NotifySpy) { actionRunInfo.SharedState.OnSpy(actionRunInfo, new ActionEndSpyEventArgs() { ActionId = actionRunInfo.ActionId, Name = actionRunInfo.Name, EndTime = DateTime.UtcNow, }); } actionRunInfo.SharedState.SuppressReactionErrors = false; }
/// <summary> /// Starts an action that changes state and recomputes the state tree. /// </summary> /// <param name="sharedState">The shared state instance to use.</param> /// <param name="actionName">The name of the action.</param> /// <param name="scope">The scope of the action.</param> /// <param name="arguments">The arguments to the action.</param> /// <returns>An <see cref="ActionRunInfo"/> instance containing the information on the currently running action.</returns> public static ActionRunInfo StartAction(ISharedState sharedState, string actionName, object scope, object[] arguments) { if (sharedState is null) { throw new ArgumentNullException(nameof(sharedState)); } if (arguments is null) { arguments = Array.Empty <object>(); } var notifySpy = !string.IsNullOrEmpty(actionName); var previousDerivation = sharedState.StartUntracked(); sharedState.StartBatch(); var previousAllowStateChanges = sharedState.StartAllowStateChanges(true); var previousAllowStateReads = sharedState.StartAllowStateReads(true); var actionRunInfo = new ActionRunInfo() { SharedState = sharedState, Name = string.IsNullOrEmpty(actionName) ? $"Action@{sharedState.NextActionId}" : actionName, PreviousDerivation = previousDerivation, PreviousAllowStateChanges = previousAllowStateChanges, PreviousAllowStateReads = previousAllowStateReads, NotifySpy = notifySpy, StartDateTime = DateTime.UtcNow, ActionId = sharedState.NextActionId++, ParentActionId = sharedState.CurrentActionId, }; if (notifySpy) { sharedState.OnSpy(actionRunInfo, new ActionStartSpyEventArgs() { Name = actionRunInfo.Name, ActionId = actionRunInfo.ActionId, Context = scope, Arguments = arguments, StartTime = actionRunInfo.StartDateTime, }); } sharedState.CurrentActionId = actionRunInfo.ActionId; return(actionRunInfo); }
/// <summary> /// Executes an Action that triggers reaction in all observables in the shared state. /// </summary> /// <param name="sharedState">The <see cref="ISharedState"/> instance to use.</param> /// <param name="actionName">The name of this action.</param> /// <param name="scope">The scope of this action.</param> /// <param name="action">The action itself.</param> /// <param name="arg1">Argument nr. 1.</param> /// <param name="arg2">Argument nr. 2.</param> internal static void ExecuteAction <T1, T2>(ISharedState sharedState, string actionName, object scope, Action <T1, T2> action, T1 arg1, T2 arg2) { ActionRunInfo actionRunInfo = StartAction(sharedState, actionName, scope, new object[] { arg1, arg2 }); try { action.Invoke(arg1, arg2); } catch (Exception exception) { actionRunInfo.Exception = exception; throw; } finally { EndAction(actionRunInfo); } }
/// <summary> /// Executes an Action that triggers reaction in all observables in the shared state. /// </summary> /// <param name="sharedState">The <see cref="ISharedState"/> instance to use.</param> /// <param name="actionName">The name of this action.</param> /// <param name="scope">The scope of this action.</param> /// <param name="action">The action itself.</param> /// <param name="arg1">Argument nr. 1.</param> /// <param name="arg2">Argument nr. 2.</param> /// <param name="arg3">Argument nr. 3.</param> /// <param name="arg4">Argument nr. 4.</param> /// <param name="arg5">Argument nr. 5.</param> /// <param name="arg6">Argument nr. 6.</param> /// <param name="arg7">Argument nr. 7.</param> /// <param name="arg8">Argument nr. 8.</param> /// <param name="arg9">Argument nr. 9.</param> /// <param name="arg10">Argument nr. 10.</param> /// <param name="arg11">Argument nr. 11.</param> /// <param name="arg12">Argument nr. 12.</param> /// <param name="arg13">Argument nr. 13.</param> /// <param name="arg14">Argument nr. 14.</param> /// <param name="arg15">Argument nr. 15.</param> /// <param name="arg16">Argument nr. 16.</param> internal static void ExecuteAction <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>(ISharedState sharedState, string actionName, object scope, Action <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) { ActionRunInfo actionRunInfo = StartAction(sharedState, actionName, scope, new object[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16 }); try { action.Invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); } catch (Exception exception) { actionRunInfo.Exception = exception; throw; } finally { EndAction(actionRunInfo); } }
/// <summary> /// Executes an Action that triggers reaction in all observables in the shared state. /// </summary> /// <param name="sharedState">The <see cref="ISharedState"/> instance to use.</param> /// <param name="actionName">The name of this action.</param> /// <param name="scope">The scope of this action.</param> /// <param name="action">The action itself.</param> internal static void ExecuteAction(ISharedState sharedState, string actionName, object scope, Action action) { ActionRunInfo actionRunInfo = StartAction(sharedState, actionName, scope, Array.Empty <object>()); try { action.Invoke(); } catch (Exception exception) { actionRunInfo.Exception = exception; throw; } finally { EndAction(actionRunInfo); } }
/// <summary> /// Executes an Action that triggers reaction in all observables in the shared state. /// </summary> /// <param name="sharedState">The <see cref="ISharedState"/> instance to use.</param> /// <param name="actionName">The name of this action.</param> /// <param name="scope">The scope of this action.</param> /// <param name="action">The action itself.</param> /// <param name="arg1">Argument nr. 1.</param> /// <param name="arg2">Argument nr. 2.</param> /// <param name="arg3">Argument nr. 3.</param> /// <param name="arg4">Argument nr. 4.</param> /// <param name="arg5">Argument nr. 5.</param> /// <param name="arg6">Argument nr. 6.</param> /// <param name="arg7">Argument nr. 7.</param> internal static void ExecuteAction <T1, T2, T3, T4, T5, T6, T7>(ISharedState sharedState, string actionName, object scope, Action <T1, T2, T3, T4, T5, T6, T7> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) { ActionRunInfo actionRunInfo = StartAction(sharedState, actionName, scope, new object[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7 }); try { action.Invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7); } catch (Exception exception) { actionRunInfo.Exception = exception; throw; } finally { EndAction(actionRunInfo); } }
/// <summary> /// Executes an Action that triggers reaction in all observables in the shared state. /// </summary> /// <param name="sharedState">The <see cref="ISharedState"/> instance to use.</param> /// <param name="actionName">The name of this action.</param> /// <param name="scope">The scope of this action.</param> /// <param name="action">The action itself.</param> /// <param name="arg1">Argument nr. 1.</param> /// <param name="arg2">Argument nr. 2.</param> /// <param name="arg3">Argument nr. 3.</param> /// <param name="arg4">Argument nr. 4.</param> /// <param name="arg5">Argument nr. 5.</param> /// <param name="arg6">Argument nr. 6.</param> /// <param name="arg7">Argument nr. 7.</param> /// <param name="arg8">Argument nr. 8.</param> /// <param name="arg9">Argument nr. 9.</param> /// <param name="arg10">Argument nr. 10.</param> /// <param name="arg11">Argument nr. 11.</param> /// <param name="arg12">Argument nr. 12.</param> /// <param name="arg13">Argument nr. 13.</param> /// <param name="arg14">Argument nr. 14.</param> /// <param name="arg15">Argument nr. 15.</param> /// <param name="arg16">Argument nr. 16.</param> internal static void ExecuteAction <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>(ISharedState sharedState, string actionName, object scope, Action <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16> action, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) { void innerAction() { ActionRunInfo actionRunInfo = StartAction(sharedState, actionName, scope, new object[] { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16 }); try { action.Invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); } catch (Exception exception) { actionRunInfo.Exception = exception; throw; } finally { EndAction(actionRunInfo); } } if (sharedState.ShouldInvoke) { var taskScheduler = sharedState.GetTaskScheduler(); Task.Factory.StartNew( () => { innerAction(); }, CancellationToken.None, TaskCreationOptions.DenyChildAttach, taskScheduler); } else { innerAction(); } }
/// <summary> /// Executes an Action that triggers reaction in all observables in the shared state. /// </summary> /// <param name="sharedState">The <see cref="ISharedState"/> instance to use.</param> /// <param name="actionName">The name of this action.</param> /// <param name="scope">The scope of this action.</param> /// <param name="action">The action itself.</param> /// <param name="arg1">Argument nr. 1.</param> internal static void ExecuteAction <T1>(ISharedState sharedState, string actionName, object scope, Action <T1> action, T1 arg1) { void innerAction() { ActionRunInfo actionRunInfo = StartAction(sharedState, actionName, scope, new object[] { arg1 }); try { action.Invoke(arg1); } catch (Exception exception) { actionRunInfo.Exception = exception; throw; } finally { EndAction(actionRunInfo); } } if (sharedState.ShouldInvoke) { var taskScheduler = sharedState.GetTaskScheduler(); Task.Factory.StartNew( () => { innerAction(); }, CancellationToken.None, TaskCreationOptions.DenyChildAttach, taskScheduler); } else { innerAction(); } }