internal static async Task RunEntityHooks <TEntity>(this ICrudRequest request,
                                                            ICrudRequestConfig config,
                                                            object entity,
                                                            CancellationToken ct)
            where TEntity : class
        {
            var hooks = config.GetEntityHooksFor <TEntity>();

            foreach (var hook in hooks)
            {
                try
                {
                    await hook.Run(request, entity, ct).Configure();

                    ct.ThrowIfCancellationRequested();
                }
                catch (Exception e) when(IsNonCancellationFailure(e))
                {
                    throw new CrudHookFailedException(GenericHookError("entity"), e)
                          {
                              HookProperty = hook
                          };
                }
            }
        }
        internal static async Task <TEntity> UpdateEntity <TEntity>(this ICrudRequest request,
                                                                    ICrudRequestConfig config,
                                                                    object item,
                                                                    TEntity entity,
                                                                    CancellationToken token)
            where TEntity : class
        {
            var updator = config.GetUpdatorFor <TEntity>();

            try
            {
                entity = await updator(request, item, entity, token).Configure();

                token.ThrowIfCancellationRequested();

                return(entity);
            }
            catch (Exception e) when(IsNonCancellationFailure(e))
            {
                throw new CrudUpdateEntityFailedException(GenericUpdateEntityError, e)
                      {
                          ItemProperty   = item,
                          EntityProperty = entity
                      };
            }
        }
        internal static async Task <T> RunResultHooks <T>(this ICrudRequest request,
                                                          ICrudRequestConfig config,
                                                          T result,
                                                          CancellationToken ct)
        {
            var hooks = config.GetResultHooks();

            foreach (var hook in hooks)
            {
                try
                {
                    if (typeof(T).IsAssignableFrom(hook.ResultType))
                    {
                        result = (T)await hook.Run(request, result, ct).Configure();
                    }
                    else
                    {
                        result = await ResultHookAdapter.Adapt(hook, request, result, ct).Configure();
                    }

                    ct.ThrowIfCancellationRequested();
                }
                catch (Exception e) when(IsNonCancellationFailure(e))
                {
                    throw new CrudHookFailedException(GenericHookError("result"), e)
                          {
                              HookProperty = hook
                          };
                }
            }

            return(result);
        }
        internal static async Task RunRequestHooks(this ICrudRequest request,
                                                   ICrudRequestConfig config,
                                                   CancellationToken ct)
        {
            var hooks = config.GetRequestHooks();

            foreach (var hook in hooks)
            {
                try
                {
                    await hook.Run(request, ct).Configure();

                    ct.ThrowIfCancellationRequested();
                }
                catch (Exception e) when(IsNonCancellationFailure(e))
                {
                    throw new CrudHookFailedException(GenericHookError("request"), e)
                          {
                              HookProperty = hook
                          };
                }
            }
        }