private bool TryMergePatches(string id, PatchRequest patchRequest)
        {
            if (DeferredCommandsDictionary.TryGetValue((id, CommandType.PATCH, null), out ICommandData command) == false)
            {
                return(false);
            }

            DeferredCommands.Remove(command);
            // We'll overwrite the DeferredCommandsDictionary when calling Defer
            // No need to call DeferredCommandsDictionary.Remove((id, CommandType.PATCH, null));

            var oldPatch  = (PatchCommandData)command;
            var newScript = oldPatch.Patch.Script + '\n' + patchRequest.Script;
            var newVals   = oldPatch.Patch.Values;

            foreach (var kvp in patchRequest.Values)
            {
                newVals[kvp.Key] = kvp.Value;
            }

            Advanced.Defer(new PatchCommandData(id, null, new PatchRequest
            {
                Script = newScript,
                Values = newVals
            }, null));

            return(true);
        }
        public void Patch <T, U>(string id, Expression <Func <T, U> > path, U value)
        {
            var pathScript = path.CompileToJavascript();

            var patchRequest = new PatchRequest
            {
                Script = $"this.{pathScript} = args.val_{_valsCount};",
                Values = { [$"val_{_valsCount}"] = value }
            };

            _valsCount++;

            if (TryMergePatches(id, patchRequest) == false)
            {
                Advanced.Defer(new PatchCommandData(id, null, patchRequest, null));
            }
        }
        public void Patch <T, U>(string id, Expression <Func <T, IEnumerable <U> > > path,
                                 Expression <Func <JavaScriptArray <U>, object> > arrayAdder)
        {
            var extension = new JavascriptConversionExtensions.CustomMethods
            {
                Suffix = _customCount++
            };
            var pathScript  = path.CompileToJavascript();
            var adderScript = arrayAdder.CompileToJavascript(
                new JavascriptCompilationOptions(
                    JsCompilationFlags.BodyOnly | JsCompilationFlags.ScopeParameter,
                    new LinqMethods(), extension));

            var patchRequest = new PatchRequest
            {
                Script = $"this.{pathScript}{adderScript}",
                Values = extension.Parameters
            };

            if (TryMergePatches(id, patchRequest) == false)
            {
                Advanced.Defer(new PatchCommandData(id, null, patchRequest, null));
            }
        }