异步编程设计模式 - IronPythonDebugger

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Microsoft.Scripting.Hosting;

using IronPython.Hosting;

using System.Threading;

using System.Windows.Forms;

using System.Reflection;

using System.ComponentModel;



namespace IronPythonDebugger

{

    public class IronPythonDebugger : IIronPythonDebugger

    {

        private ScriptEngine _engine;



        private ScriptScope _scope;



        private string _source;



        private string _debugSource;



        private ScriptSource _debugScriptSource;



        private Dictionary<int, bool> _breakpoints;



        private Thread _debugThread;



        private int _currentLine = 0;//从1开始计算



        private int _logicStartLine;//从1开始计算



        private ScriptBackgroundExecute _backgroundExecute;



        private bool _debugging = false;



        private int _sourceLineCount;



        private const string BACKGROUND_BREAK_CODE = "_backgroundExecute.Break()";



        private Action<int> _breakCallback;



        private int _nextBreakLine;



        private bool _debugThreadSleep = false;



        private AsyncOperation _asyncOp;



        private Action _exec;



        private SendOrPostCallback _onBreakCallback;



        private void Execute()

        {

            try

            {

                _debugScriptSource.Execute(_scope);

            }

            catch (DebugStopException)

            {

            }

            catch (ThreadAbortException)

            {

            }

            catch (Exception e)

            {

                throw new Exception(e.Message);

            }

            finally

            {

                Stop();

            }

        }



        private void BackgroundBreakCallback()

        {

            if (!_debugging)

            {

                throw new DebugStopException();

            }

            _currentLine++;

            if (_currentLine == _nextBreakLine)

            {

                _debugThreadSleep = true;

                //if (_breakCallback != null)

                //{

                //    _breakCallback(_currentLine);

                //}

                _asyncOp.Post(_onBreakCallback, _currentLine);

                WaitDebugThreadContinue();

            }

        }



        private void OnBreakCallback(object lineNumber)

        {

            if (Break != null)

            {

                Break(this, new BreakEventArgs((int)lineNumber));

            }

            else if (_breakCallback != null)

            {

                _breakCallback((int)lineNumber);

            }

        }



        private void WaitDebugThreadContinue()

        {

            while (_debugThreadSleep)

            {

                Thread.Sleep(100);

            }

        }



        private void AddBackgroundBreakCode()

        {

            string[] lines = _source.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);

            _sourceLineCount = lines.Length;

            _logicStartLine = GetLogicStartLine(lines);//获取第一行逻辑代码的行号

            _debugSource = string.Empty;

            for (int i = 0; i < _sourceLineCount; i++)

            {

                if (!string.IsNullOrEmpty(_debugSource))

                {

                    _debugSource += Environment.NewLine;

                }

                if (i >= _logicStartLine - 1)

                {

                    _debugSource += BACKGROUND_BREAK_CODE + Environment.NewLine;

                }

                _debugSource += lines[i];

            }

        }



        ////import clr,sys

        ////clr.AddReference('TestClass')

        ////clr.AddReference('System.Windows.Forms')

        ////from TestClass import *

        ////from System.Windows.Forms import *



        ////c1 = Class1()

        ////c1.Name = "c1"

        ////MessageBox.Show(c1.Name)

        ////child = Class1()

        ////child.Name = "child1"

        ////c1.Child = child

        ////MessageBox.Show(c1.Child.Name)

        private int GetLogicStartLine(string[] lines)

        {

            int startLine = 1;

            for (int i = 0; i < lines.Length;i++ )

            {

                string line = lines[i].ToLower();

                if (line.IndexOf("import") < 0

                    && line.IndexOf("clr") < 0

                    && line.IndexOf("from") < 0)

                {

                    startLine = i + 1;

                    break;

                }

            }

            return startLine;

        }



        private int GetNextBreakLine(int currentLine)

        {

            int next = -1;

            _breakpoints.OrderBy(breakpoint => breakpoint.Key);

            foreach (KeyValuePair<int, bool> breakpoint in _breakpoints)

            {

                if (breakpoint.Value && breakpoint.Key > currentLine)

                {

                    next = breakpoint.Key;

                    break;

                }

            }

            return next;

        }



        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////



        public event Action<object, BreakEventArgs> Break;



        public ScriptEngine Engine

        {

            get

            {

                return _engine;

            }

        }



        public ScriptScope Scope

        {

            get

            {

                return _scope;

            }

        }



        public string Source

        {

            get

            {

                return _source;

            }

        }



        public Action<int> BreakCallback

        {

            get

            {

                return _breakCallback;

            }



            set

            {

                _breakCallback = value;

            }

        }



        public IronPythonDebugger()

        {

            _engine = Python.CreateEngine();

            _scope = _engine.CreateScope();

            _scope.SetVariable("_backgroundExecute", _backgroundExecute);

            _breakpoints = new Dictionary<int, bool>();

            _backgroundExecute = new ScriptBackgroundExecute(BackgroundBreakCallback);

            _exec = new Action(Execute);

            _onBreakCallback = new SendOrPostCallback(OnBreakCallback);

        }



        public void InitialDebugger()

        {

            if (_debugging)

            {

                throw new Exception("调试器正在调试中!");

            }

            _scope = _engine.CreateScope();

            _scope.SetVariable("_backgroundExecute", _backgroundExecute);

            _breakpoints.Clear();

        }



        public void InitialDebugger(List<int> breakpoints)

        {

            InitialDebugger();

            foreach (int breakpoint in breakpoints)

            {

                _breakpoints[breakpoint] = true;

            }

        }



        public void ClearBreakpoints()

        {

            _breakpoints.Clear();

        }



        public void Start(string source)

        {

            if (_debugging)

            {

                throw new Exception("调试器正在调试中!");

            }

            _source = source;

            AddBackgroundBreakCode();

            _debugScriptSource = _engine.CreateScriptSourceFromString(_debugSource);

            _currentLine = _logicStartLine - 1;

            _debugThreadSleep = false;

            _nextBreakLine = GetNextBreakLine(0);

            //_debugThread = new Thread(Execute);

            //_debugThread.Start();

            _asyncOp = AsyncOperationManager.CreateOperation(1);

            _exec.BeginInvoke(null, null);

            _debugging = true;

        }



        public void Stop()

        {

            if (_debugging)

            {

                _debugging = false;

                _debugThreadSleep = false;

                //if (_debugThread != null && _debugThread.IsAlive)

                //{

                //    _debugThread.Abort();

                //}

            }

        }



        public void AddBreakpoint(int line)

        {

            _breakpoints[line] = true;

        }



        public void AddBreakpoints(List<int> lines)

        {

            foreach (int line in lines)

            {

                AddBreakpoint(line);

            }

        }



        public void DeleteBreakpoint(int line)

        {

            _breakpoints[line] = false;

        }



        public void DeleteBreakpoints(List<int> lines)

        {

            foreach (int line in lines)

            {

                DeleteBreakpoint(line);

            }

        }



        public void StepOver()

        {

            if (!_debugging)

            {

                throw new Exception("调试器未开始调试!");

            }

            _nextBreakLine++;

            _debugThreadSleep = false;

        }



        public void StepInto()

        {

            MessageBox.Show("暂不支持逐语句调试!");

        }



        public void StepOut()

        {

            MessageBox.Show("暂不支持跳出调试!");

        }



        public void Continue()

        {

            if (!_debugging)

            {

                throw new Exception("调试器未开始调试!");

            }

            _nextBreakLine = GetNextBreakLine(_currentLine);

            _debugThreadSleep = false;

        }



        public string GetValueAsString(string variable)

        {

            string value = string.Empty;

            try

            {

                string[] names = variable.Split('.');

                object obj = _scope.GetVariable(names[0]);

                for (int i = 1; i < names.Length; i++)

                {

                    Type type = obj.GetType();

                    PropertyInfo pi = type.GetProperty(names[i]);

                    obj = pi.GetValue(obj, null);

                }

                value = obj.ToString();

            }

            catch (Exception e)

            {

                throw new Exception(e.Message);

            }

            return value;

        }



        public bool IsDebugging()

        {

            return _debugging;

        }

    }



    public class BreakEventArgs : EventArgs

    {

        public int LineNumber;



        public BreakEventArgs(int lineNumber)

        {

            this.LineNumber = lineNumber;

        }

    }



    public class DebugStopException : Exception

    {

    }

}

 

你可能感兴趣的:(debugger)