示例#1
0
        /// <summary>
        /// Select an applicable function without executing it
        /// </summary>
        /// <typeparam name="T">Generic type</typeparam>
        /// <param name="context">gate context</param>
        /// <param name="mode">mode to run the gated code in</param>
        /// <param name="conditionalPredicate">The conditional predicate.</param>
        /// <param name="functions">array of gated functions</param>
        /// <param name="keepContext">controls whether async operation should keep the synchronization context</param>
        /// <remarks>
        /// keep context should be set to true in code which is async end to end,
        /// and false in other cases to avoid deadlocking
        /// </remarks>
        /// <returns>a function to perform, never null</returns>
        public static Func <Task <T> > SelectFunction <T>(this IGateContext context, GatedCode.Modes mode, Func <bool> conditionalPredicate,
                                                          GatedAsyncFunc <T>[] functions, bool keepContext)
        {
            Tuple <GatedAsyncFunc <T>, IGate[]> action = SelectCode(context, conditionalPredicate, functions);

            if (action?.Item1 == null)
            {
                return(() => Task.FromResult(default(T)));
            }

            return(async() =>
            {
                context.EnterScopes(mode, action.Item2);

                try
                {
                    if (action.Item1.Func != null)
                    {
                        return await action.Item1.Func().ConfigureAwait(keepContext);
                    }
                }
                finally
                {
                    context.ExitScopes(mode, action.Item2);
                }

                return default(T);
            });
        }
示例#2
0
        /// <summary>
        /// Select an applicable function without executing it
        /// </summary>
        /// <param name="context">gate context</param>
        /// <param name="mode">mode to run the gated code in</param>
        /// <param name="functions">array of gated functions</param>
        /// <returns>a function to perform, never null</returns>
        public static Func <T, T> SelectFunction <T>(this IGateContext context, GatedCode.Modes mode, params GatedFunc <T, T>[] functions)
        {
            Tuple <GatedFunc <T, T>, IGate[]> action = SelectCode(context, null, functions);

            if (action != null && action.Item1 != null)
            {
                return(new Func <T, T>(
                           (t) =>
                {
                    context.EnterScopes(mode, action.Item2);

                    try
                    {
                        if (action.Item1.Func != null)
                        {
                            return action.Item1.Func(t);
                        }
                    }
                    finally
                    {
                        context.ExitScopes(mode, action.Item2);
                    }

                    return t;
                }));
            }

            return(new Func <T, T>((t) => t));
        }
示例#3
0
        /// <summary>
        /// Select an applicable action without executing it
        /// </summary>
        /// <param name="context">gate context</param>
        /// <param name="mode">mode to run the gated code in</param>
        /// <param name="conditionalPredicate">The conditional predicate.</param>
        /// <param name="actions">array of gated actions</param>
        /// <param name="keepContext">controls whether async operation should keep the synchronization context</param>
        /// <remarks>
        /// keep context should be set to true in code which is async end to end,
        /// and false in other cases to avoid deadlocking
        /// </remarks>
        /// <returns>an action to perform, never null</returns>
        public static Func <Task> SelectAction(this IGateContext context, GatedCode.Modes mode, Func <bool> conditionalPredicate, GatedAsyncAction[] actions, bool keepContext = false)
        {
            Tuple <GatedAsyncAction, IGate[]> action = SelectCode(context, conditionalPredicate, actions);

            if (action?.Item1 == null)
            {
                return(s_noOpAction);
            }

            return(async() =>
            {
                context.EnterScopes(mode, action.Item2);

                try
                {
                    if (action.Item1?.Action != null)
                    {
                        await action.Item1.Action().ConfigureAwait(keepContext);
                    }
                }
                finally
                {
                    context.ExitScopes(mode, action.Item2);
                }
            });
        }
示例#4
0
        /// <summary>
        /// Select an applicable function without executing it
        /// </summary>
        /// <typeparam name="T">Generic type</typeparam>
        /// <param name="context">gate context</param>
        /// <param name="mode">mode to run the gated code in</param>
        /// <param name="conditionalPredicate">The conditional predicate.</param>
        /// <param name="functions">array of gated functions</param>
        /// <returns>a function to perform, never null</returns>
        public static Func <T> SelectFunction <T>(this IGateContext context, GatedCode.Modes mode, Func <bool> conditionalPredicate,
                                                  params GatedFunc <T>[] functions)
        {
            Tuple <GatedFunc <T>, IGate[]> action = SelectCode(context, conditionalPredicate, functions);

            if (action != null && action.Item1 != null)
            {
                return(new Func <T>(
                           () =>
                {
                    context.EnterScopes(mode, action.Item2);

                    try
                    {
                        if (action.Item1.Func != null)
                        {
                            return action.Item1.Func();
                        }
                    }
                    finally
                    {
                        context.ExitScopes(mode, action.Item2);
                    }
                    return default(T);
                }));
            }

            return(new Func <T>(() => default(T)));
        }
示例#5
0
 /// <summary>
 /// Exit a scope for gated code
 /// </summary>
 /// <param name="context">the gate context</param>
 /// <param name="mode">mode that code should be performed (e.g. scoped or not)</param>
 /// <param name="gate">the gate to exit scope for</param>
 public static void ExitScope(this IGateContext context, GatedCode.Modes mode, IGate gate)
 {
     if (context.ShouldBeScoped((mode & GatedCode.Modes.ExitScope), gate))
     {
         context.ExitScope(gate);
     }
 }
示例#6
0
        /// <summary>
        /// Should the context scope the code
        /// </summary>
        /// <param name="context">gate context</param>
        /// <param name="mode">preferred mode for code</param>
        /// <param name="gate">gate to run</param>
        /// <returns>true if the context should scope the code, false otherwise</returns>
        private static bool ShouldBeScoped(this IGateContext context, GatedCode.Modes mode, IGate gate)
        {
            if (gate == null)
            {
                return(false);
            }

            if (context == null)
            {
                return(false);
            }

            if ((mode & GatedCode.Modes.EnterScope) == GatedCode.Modes.EnterScope ||
                (mode & GatedCode.Modes.ExitScope) == GatedCode.Modes.ExitScope)
            {
                return(true);
            }

            if (context.Request != null && context.Request.RequestedGateIds != null &&
                context.Request.RequestedGateIds.Contains(gate.Name))
            {
                return(true);
            }

            return(false);
        }
示例#7
0
 /// <summary>
 /// Perform each function that is applicable in the current gate context. The input parameter
 /// is passed to the first applicable function, and the result of that function is used as the input
 /// for the next applicable function, etc. This allows for chaining multiple functions, each having
 /// an opportunity to modify the input.
 /// </summary>
 /// <param name="context">gate context</param>
 /// <param name="input">the input object</param>
 /// <param name="mode">mode to run the gated code in</param>
 /// <param name="functions">array of gated functions</param>
 /// <typeparam name="T">the return type of the function</typeparam>
 /// <returns>instance of T (default if no applicable action found)</returns>
 public static T PerformEachFunction <T>(this IGateContext context, GatedCode.Modes mode, T input, params GatedFunc <T, T>[] functions)
 {
     Array.ForEach(functions,
                   (function) =>
     {
         input = SelectFunction(context, mode, function)(input);
     }
                   );
     return(input);
 }
示例#8
0
        /// <summary>
        /// Exits a collection of scopes in a reverse order.
        /// </summary>
        /// <param name="context">The gate context.</param>
        /// <param name="mode">The mode that code should be performed.</param>
        /// <param name="gates">The array of gates for exiting the scope.</param>
        public static void ExitScopes(this IGateContext context, GatedCode.Modes mode, IGate[] gates)
        {
            if (gates == null)
            {
                return;
            }

            for (int i = gates.Length - 1; i >= 0; i--)
            {
                ExitScope(context, mode, gates[i]);
            }
        }
示例#9
0
        /// <summary>
        /// Enters a collection of scopes in a nested way.
        /// </summary>
        /// <param name="context">The gate context.</param>
        /// <param name="mode">The mode that code should be performed.</param>
        /// <param name="gates">The array of gates for the scope.</param>
        public static void EnterScopes(this IGateContext context, GatedCode.Modes mode, IGate[] gates)
        {
            if (gates == null)
            {
                return;
            }

            foreach (IGate gate in gates)
            {
                EnterScope(context, mode, gate);
            }
        }
示例#10
0
        /// <summary>
        /// Select an applicable action without executing it
        /// </summary>
        /// <param name="context">gate context</param>
        /// <param name="mode">mode to run the gated code in</param>
        /// <param name="conditionalPredicate">The conditional predicate.</param>
        /// <param name="actions">array of gated actions</param>
        /// <returns>an action to perform, never null</returns>
        public static Action SelectAction(this IGateContext context, GatedCode.Modes mode, Func <bool> conditionalPredicate, params GatedAction[] actions)
        {
            Tuple <GatedAction, IGate[]> action = SelectCode(context, conditionalPredicate, actions);

            if (action != null && action.Item1 != null)
            {
                return(new Action(
                           () =>
                {
                    context.EnterScopes(mode, action.Item2);

                    try
                    {
                        action.Item1.Action?.Invoke();
                    }
                    finally
                    {
                        context.ExitScopes(mode, action.Item2);
                    }
                }));
            }

            return(new Action(() => { }));
        }
示例#11
0
 /// <summary>
 /// Perform an action that is applicable in the current gate context
 /// </summary>
 /// <param name="context">gate context</param>
 /// <param name="mode">mode to run the gated code in</param>
 /// <param name="actions">array of gated actions</param>
 public static Task PerformAction(this IGateContext context, GatedCode.Modes mode, params GatedAsyncAction[] actions) => SelectAction(context, mode, null, actions)();
示例#12
0
        /// <summary>
        /// Select an applicable function without executing it
        /// </summary>
        /// <param name="context">gate context</param>
        /// <param name="mode">mode to run the gated code in</param>
        /// <param name="functions">array of gated functions</param>
        /// <param name="keepContext">controls whether async operation should keep the synchronization context</param>
        /// <remarks>
        /// keep context should be set to true in code which is async end to end,
        /// and false in other cases to avoid deadlocking
        /// </remarks>
        /// <returns>a function to perform, never null</returns>
        public static Func <T, Task <T> > SelectFunction <T>(this IGateContext context, GatedCode.Modes mode, GatedAsyncFunc <T, T>[] functions, bool keepContext)
        {
            Tuple <GatedAsyncFunc <T, T>, IGate[]> action = SelectCode(context, null, functions);

            if (action != null && action.Item1 != null)
            {
                return(async t =>
                {
                    context.EnterScopes(mode, action.Item2);

                    try
                    {
                        if (action.Item1.Func != null)
                        {
                            return await action.Item1.Func(t).ConfigureAwait(keepContext);
                        }
                    }
                    finally
                    {
                        context.ExitScopes(mode, action.Item2);
                    }

                    return t;
                });
            }

            return(Task.FromResult);
        }
示例#13
0
 /// <summary>
 /// Select an applicable function without executing it
 /// </summary>
 /// <param name="context">gate context</param>
 /// <param name="mode">mode to run the gated code in</param>
 /// <param name="functions">array of gated functions</param>
 /// <returns>a function to perform, never null</returns>
 public static Func <T, Task <T> > SelectFunction <T>(this IGateContext context, GatedCode.Modes mode, params GatedAsyncFunc <T, T>[] functions)
 {
     return(SelectFunction(context, mode, functions, false));
 }
示例#14
0
 /// <summary>
 /// Perform each action that is applicable in the current gate context
 /// </summary>
 /// <param name="context">gate context</param>
 /// <param name="mode">mode to run the gated code in</param>
 /// <param name="actions">array of gated actions</param>
 public static void PerformEachAction(this IGateContext context, GatedCode.Modes mode, params GatedAction[] actions)
 {
     Array.ForEach(actions, (action) => PerformAction(context, mode, action));
 }
示例#15
0
 /// <summary>
 /// Select an applicable action without executing it
 /// </summary>
 /// <param name="context">gate context</param>
 /// <param name="mode">mode to run the gated code in</param>
 /// <param name="conditionalPredicate">The conditional predicate.</param>
 /// <param name="actions">array of gated actions</param>
 /// <returns>an action to perform, never null</returns>
 public static Func <Task> SelectAction(this IGateContext context, GatedCode.Modes mode, Func <bool> conditionalPredicate, params GatedAsyncAction[] actions)
 {
     return(SelectAction(context, mode, conditionalPredicate, actions, false));
 }
示例#16
0
 /// <summary>
 /// Select an applicable function without executing it
 /// </summary>
 /// <typeparam name="T">Generic type</typeparam>
 /// <param name="context">gate context</param>
 /// <param name="mode">mode to run the gated code in</param>
 /// <param name="conditionalPredicate">The conditional predicate.</param>
 /// <param name="functions">array of gated functions</param>
 /// <returns>a function to perform, never null</returns>
 public static Func <Task <T> > SelectFunction <T>(this IGateContext context, GatedCode.Modes mode, Func <bool> conditionalPredicate,
                                                   params GatedAsyncFunc <T>[] functions)
 {
     return(SelectFunction(context, mode, conditionalPredicate, functions, false));
 }
示例#17
0
 /// <summary>
 /// Perform a function that is applicable in the current gate context
 /// </summary>
 /// <param name="context">gate context</param>
 /// <param name="mode">mode to run the gated code in</param>
 /// <param name="functions">array of gated functions</param>
 /// <typeparam name="T">the return type of the function</typeparam>
 /// <returns>instance of T (default if no applicable action found)</returns>
 public static Task <T> PerformFunction <T>(this IGateContext context, GatedCode.Modes mode, params GatedAsyncFunc <T>[] functions) => SelectFunction(context, mode, null, functions)();