本帖最后由 秋声赋 于 2012-8-8 21:57 编辑
[mw_shl_code=csharp,true]using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using IronRuby;
using IronRuby.StandardLibrary.BigDecimal;
using Microsoft.Scripting;
using Microsoft.Scripting.Hosting;
using Runa.WPF.Content;
namespace ScriptingHost
{
public class RuntimeErrorEventArgs : EventArgs
{
public Exception Error { get; set; }
public RuntimeErrorEventArgs()
: base()
{
}
public RuntimeErrorEventArgs(Exception e)
{
this.Error = e;
}
}
public class CompilationErrorEventArgs : EventArgs
{
public ScriptSource ScriptSource { get; set; }
public string Message { get; set; }
public SourceSpan SourceSpan { get; set; }
public int ErrorCode { get; set; }
public Severity Severity { get; set; }
public CompilationErrorEventArgs(Microsoft.Scripting.Hosting.ScriptSource source, string message, Microsoft.Scripting.SourceSpan span, int errorCode, Microsoft.Scripting.Severity severity)
{
this.ScriptSource = source;
this.Message = message;
this.SourceSpan = span;
this.ErrorCode = errorCode;
this.Severity = severity;
}
}
public class CompilationErrorListener : Microsoft.Scripting.Hosting.ErrorListener
{
public EventHandler *本站禁止HTML标签噢* Handler { get; set; }
public CompilationErrorListener(EventHandler *本站禁止HTML标签噢* handler)
{
this.Handler = handler;
}
public override void ErrorReported(Microsoft.Scripting.Hosting.ScriptSource source, string message, Microsoft.Scripting.SourceSpan span, int errorCode, Microsoft.Scripting.Severity severity)
{
this.Handler.Invoke(this, new CompilationErrorEventArgs(source, message, span, errorCode, severity));
}
}
public class ScriptTask
{
public string Name { get; set; }
public DateTime CommitTime { get; set; }
public string ScriptType { get; set; }
public object Result { get; set; }
public Exception LastError { get; set; }
public string Script
{
get { return this.m_script; }
set
{
this.m_script = value;
if (string.IsNullOrEmpty(this.m_script))
{
return;
}
else
{
if (this.ScriptScope == null)
{
this.ScriptScope = ScriptTask.Engine.CreateScriptSourceFromString(this.Script);
this.CompiledCode = this.ScriptScope.Compile(new CompilationErrorListener(OnCompilationFailed));
}
}
}
}
public static ScriptEngine Engine { get; set; }
private ScriptSource ScriptScope { get; set; }
private CompiledCode CompiledCode { get; set; }
private string m_script = "";
private Dictionary<string, Tuple<ScriptSource, CompiledCode>> m_compiledCodes = new Dictionary<string, Tuple<ScriptSource, CompiledCode>>();
public event OnRuntimeErrorEventHandler OnRuntimeError;
public delegate void OnRuntimeErrorEventHandler(object sender, RuntimeErrorEventArgs e);
public event OnCompilationErrorEventHandler OnCompilationError;
public delegate void OnCompilationErrorEventHandler(object sender, CompilationErrorEventArgs e);
public ScriptTask(string code = "")
{
if (ScriptTask.Engine == null)
{
ScriptTask.Engine = Ruby.CreateEngine();
}
this.LoadAssembly(typeof(BigDecimal).Assembly);
this.Script = code;
this.GlobalVariablesName = new List *本站禁止HTML标签噢* ();
}
public void LoadAssembly(System.Reflection.Assembly assembly)
{
Engine.Runtime.LoadAssembly(assembly);
}
public void LoadScriptFromIsolatedStorage(string path, IsolatedStorageFile fileStorage)
{
try
{
using (var fs = fileStorage.OpenFile(path, FileMode.Open))
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(fs))
{
this.Script = sr.ReadToEnd();
sr.Close();
}
fs.Close();
}
this.AddBasicReference(this);
}
catch (Exception ex)
{
throw ex;
}
}
public bool Execute(params WpfApplication4.Tuple<string, object>[] args)
{
try
{
if (string.IsNullOrEmpty(this.Script))
{
return false;
}
else
{
while (true)
{
if (this.ScriptScope != null)
{
if (this.ScriptScope.GetCode() == this.Script)
{
break; // TODO: might not be correct. Was : Exit While
}
}
this.ScriptScope = ScriptTask.Engine.CreateScriptSourceFromString(this.Script);
this.CompiledCode = this.ScriptScope.Compile(new CompilationErrorListener(OnCompilationFailed));
break; // TODO: might not be correct. Was : Exit While
}
}
foreach (var v in args)
{
this.CompiledCode.Engine.Runtime.Globals.SetVariable(v.Item1, v.Item2);
}
this.Result = this.CompiledCode.Execute();
return true;
}
catch (Exception ex)
{
this.LastError = ex;
if (OnRuntimeError != null)
{
OnRuntimeError(this, new RuntimeErrorEventArgs(ex));
}
return false;
}
}
public bool Execute(string expression, params WpfApplication4.Tuple<string, object>[] args)
{
try
{
if (string.IsNullOrEmpty(this.m_script))
{
throw new ArgumentException("Null or empty script to execute.");
return false;
}
else
{
if (string.IsNullOrEmpty(expression) == false)
{
var code = this.m_script + Environment.NewLine + expression;
while (true)
{
if (this.m_compiledCodes.ContainsKey(code))
{
if (this.m_compiledCodes[code].Item1.GetCode() == code)
{
this.CompiledCode = this.m_compiledCodes[code].Item2;
break; // TODO: might not be correct. Was : Exit While
}
}
this.ScriptScope = ScriptTask.Engine.CreateScriptSourceFromString(code);
this.CompiledCode = this.ScriptScope.Compile(new CompilationErrorListener(OnCompilationFailed));
this.m_compiledCodes.Add(code, new Tuple<ScriptSource, CompiledCode>(this.ScriptScope, this.CompiledCode));
break; // TODO: might not be correct. Was : Exit While
}
}
else
{
throw new ArgumentException("Null or empty expression to execute.");
return false;
}
}
foreach (var v in args)
{
this.CompiledCode.Engine.Runtime.Globals.SetVariable(v.Item1, v.Item2);
}
CheakGlobalsName(expression);
this.Result = this.CompiledCode.Execute();
return true;
}
catch (Exception ex)
{
this.LastError = ex;
if (OnRuntimeError != null)
{
OnRuntimeError(this, new RuntimeErrorEventArgs(ex));
}
return false;
}
}
private void OnCompilationFailed(object sender, CompilationErrorEventArgs e)
{
if (OnCompilationError != null)
{
OnCompilationError(sender, e);
}
}
private void AddBasicReference(ScriptTask spt)
{
var _with1 = spt;
_with1.LoadAssembly(this.GetType().Assembly);
}
//========上面是Long写好给我的,稍微修改了下,本来会判断Ruby还是Python的
//========但是目前引擎还不会使用Python,所以我就删掉了
//========下面是我自己写的,用来保存那些全局变量的
//========能保存全局变量的话,就能做存档功能了
//========SerializableDictionary是自己写的能序列化的字典
public List *本站禁止HTML标签噢* GlobalVariablesName
{ get; set; }
private void CheakGlobalsName(string code)
{
if (code.Contains("$") && code.Contains("="))
{
code = code.Replace(" ", "");
int index = code.IndexOf('$');
int endindex = code.IndexOf('=');
if (index < endindex)
{
string pattern = @"^[A-Za-z0-9$]+$";
Regex regex = new Regex(pattern);
if (regex.IsMatch(code.Substring(index, endindex)))
{
GlobalVariablesName.Add(code.Substring(index, endindex));
}
}
}
}
public System.Collections.Generic.Dictionary<string, string> GetGlobals()
{
System.Collections.Generic.Dictionary<string, string> result = new Dictionary<string, string>();
for (int i = 0; i < this.GlobalVariablesName.Count; i++)
{
var ex = "return " + this.GlobalVariablesName;
this.Execute(ex);
if (this.Result.GetType() == typeof(IronRuby.Builtins.MutableString))
{
result.Add(this.GlobalVariablesName, "\""+this.Result.ToString()+"\"");
}
else
{
result.Add(this.GlobalVariablesName, this.Result.ToString());
}
}
return result;
}
public void SaveGlobals(Stream fs)
{
SerializableDictionary<string, string> r = new SerializableDictionary<string, string>(this.GetGlobals());
XmlSerializer xs = new XmlSerializer(r.GetType());
xs.Serialize(fs, r);
fs.Close();
}
public void LoadGlobale(Stream fs)
{
XmlSerializer xs = new XmlSerializer(typeof(SerializableDictionary<string, string>));
var s= xs.Deserialize(fs) as SerializableDictionary<string, string>;
fs.Close();
foreach (var k in s.Keys)
{
this.Execute(k + "=" + s[k]);
}
}
}
}[/mw_shl_code]
如果有人需要的话,我可以解释下