/// <summary>
        /// Creates a new <see cref="InterprocessDebuggerClient"/>, using the information provided by the <see cref="InterprocessDebuggerServer"/> to open the pipes to communicate with it.
        /// </summary>
        /// <param name="args">The arguments with which the <see cref="InterprocessDebuggerServer"/> started the client process.</param>
        public InterprocessDebuggerClient(string[] args)
        {
            ParentProcess = Process.GetProcessById(int.Parse(args[0]));
            if (ParentProcess != null)
            {
                ParentProcess.EnableRaisingEvents = true;

                ParentProcess.Exited += (s, e) =>
                {
                    if (!ParentProcessExitedRaised)
                    {
                        ParentProcessExitedRaised = true;
                        ParentProcessExited?.Invoke(this, new EventArgs());
                    }
                };
            }

            PipeClientIn = new NamedPipeClientStream(".", args[1], PipeDirection.In);

            PipeClientOut = new NamedPipeClientStream(".", args[2], PipeDirection.Out);

            PipeClientIn.Connect();
            PipeClientOut.Connect();

            PipeClientOutWriter = new StreamWriter(PipeClientOut);
            PipeClientInReader  = new StreamReader(PipeClientIn);


            string message = PipeClientInReader.ReadLine();

            PipeClientOutWriter.WriteLine(message);
            PipeClientOutWriter.Flush();
        }
        /// <summary>
        /// Start the loop that waits for breakpoint signals from the server.
        /// </summary>
        /// <param name="e">The event args.</param>
        protected override async void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
        {
            base.OnAttachedToLogicalTree(e);

            if (Editor == null)
            {
                Editor = await Editor.Create();

                Editor.AccessType = Editor.AccessTypes.ReadOnly;
                this.Content      = Editor;
            }

            while (!ParentProcess.HasExited)
            {
                string message = await PipeClientInReader.ReadLineAsync();

                if (message == "Abort")
                {
                    if (!ParentProcessExitedRaised)
                    {
                        ParentProcessExitedRaised = true;
                        ParentProcessExited?.Invoke(this, new EventArgs());
                    }
                    break;
                }

                if (!ParentProcess.HasExited && message == "Init")
                {
                    message = await PipeClientInReader.ReadLineAsync();

                    if (message == "Abort")
                    {
                        if (!ParentProcessExitedRaised)
                        {
                            ParentProcessExitedRaised = true;
                            ParentProcessExited?.Invoke(this, new EventArgs());
                        }
                        break;
                    }

                    if (!ParentProcess.HasExited && !string.IsNullOrEmpty(message))
                    {
                        string[] messageParts = JsonSerializer.Deserialize <string[]>(message);

                        string[][] localVariablesDisplayPartsJson = JsonSerializer.Deserialize <string[][]>(messageParts[0]);
                        string[][] localVariablesJson             = JsonSerializer.Deserialize <string[][]>(messageParts[1]);
                        string     sourceCode      = messageParts[2];
                        int        breakpointStart = int.Parse(messageParts[3]);
                        string     preSource       = messageParts[4];
                        string     postSource      = messageParts[5];

                        IEnumerable <CachedMetadataReference> references = from el in JsonSerializer.Deserialize <string[]>(messageParts[6]) select CachedMetadataReference.CreateFromFile(el);

                        Dictionary <string, TaggedText[]> localVariablesDisplayParts = new Dictionary <string, TaggedText[]>();

                        foreach (string[] item in localVariablesDisplayPartsJson)
                        {
                            localVariablesDisplayParts.Add(item[0], (from el in JsonSerializer.Deserialize <ReadWriteTaggedText[]>(item[1]) select(TaggedText) el).ToArray());
                        }

                        Dictionary <string, (string, VariableTypes, object)> localVariables = new Dictionary <string, (string, VariableTypes, object)>();

                        foreach (string[] item in localVariablesJson)
                        {
                            VariableTypes variableType = JsonSerializer.Deserialize <VariableTypes>(item[2]);

                            object variableValue = ParseVariableValue(variableType, item[3]);

                            localVariables.Add(item[0], (item[1], variableType, variableValue));
                        }

                        (string propertyId, VariableTypes propertyType, object propertyValue) propertyOrFieldGetter(string variableId, string propertyName, bool isProperty)
                        {
                            PipeClientOutWriter.WriteLine(JsonSerializer.Serialize(new string[] { "GetProperty", variableId, propertyName, isProperty.ToString() }));
                            PipeClientOutWriter.Flush();

                            string message = PipeClientInReader.ReadLine();

                            if (message == "Abort")
                            {
                                if (!ParentProcessExitedRaised)
                                {
                                    ParentProcessExitedRaised = true;
                                    ParentProcessExited?.Invoke(this, new EventArgs());
                                }
                                return("", VariableTypes.Null, "");
                            }

                            string[] output = JsonSerializer.Deserialize <string[]>(message);

                            VariableTypes variableType = JsonSerializer.Deserialize <VariableTypes>(output[1]);

                            return(output[0], variableType, ParseVariableValue(variableType, output[2]));
                        }

                        (string itemId, VariableTypes itemType, object itemValue)[] itemsGetter(string variableId)