代码拉取完成,页面将自动刷新
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Windows.Forms;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
namespace AppBasicIDE
{
public class ScriptEngine
{
private Dictionary<string, Assembly> _compiledScripts = new Dictionary<string, Assembly>();
private ControlManager _controlManager;
public ScriptEngine(ControlManager controlManager = null)
{
_controlManager = controlManager;
}
public void SetControlManager(ControlManager controlManager)
{
_controlManager = controlManager;
}
public bool CompileScript(string scriptId, string code, out string error)
{
error = null;
try
{
// 生成控件访问代码
var controlAccessCode = GenerateControlAccessCode();
// 包装代码到一个类中,包含控件访问功能
var wrappedCode = $@"
using System;
using System.Windows.Forms;
using System.Drawing;
public class ScriptClass
{{
private System.Collections.Generic.Dictionary<string, Control> _controls;
public void SetControls(System.Collections.Generic.Dictionary<string, Control> controls)
{{
_controls = controls;
}}
{controlAccessCode}
public void Execute(Control sender, EventArgs e)
{{
{code}
}}
}}";
var syntaxTree = CSharpSyntaxTree.ParseText(wrappedCode);
// 获取所有必要的引用程序集
var references = GetMetadataReferences();
var compilation = CSharpCompilation.Create(
assemblyName: $"Script_{scriptId}_{Guid.NewGuid():N}",
syntaxTrees: new[] { syntaxTree },
references: references,
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
using (var ms = new MemoryStream())
{
EmitResult result = compilation.Emit(ms);
if (!result.Success)
{
var failures = result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error);
error = string.Join("\n", failures.Select(f => f.GetMessage()));
return false;
}
ms.Seek(0, SeekOrigin.Begin);
var assembly = Assembly.Load(ms.ToArray());
_compiledScripts[scriptId] = assembly;
return true;
}
}
catch (Exception ex)
{
error = ex.Message;
return false;
}
}
private string GenerateControlAccessCode()
{
if (_controlManager == null) return "";
var sb = new StringBuilder();
// 生成每个控件的访问属性
foreach (var controlName in _controlManager.GetAllControlNames())
{
var designControl = _controlManager.FindControlByName(controlName);
if (designControl?.InnerControl != null)
{
var controlType = designControl.InnerControl.GetType().Name;
sb.AppendLine($@"
public {controlType} {controlName}
{{
get
{{
if (_controls != null && _controls.ContainsKey(""{controlName}""))
return _controls[""{controlName}""] as {controlType};
return null;
}}
}}");
}
}
// 添加通用的查找方法
sb.AppendLine(@"
public Control FindControl(string name)
{
if (_controls != null && _controls.ContainsKey(name))
return _controls[name];
return null;
}
public T FindControl<T>(string name) where T : Control
{
return FindControl(name) as T;
}");
return sb.ToString();
}
private MetadataReference[] GetMetadataReferences()
{
var references = new List<MetadataReference>();
var addedAssemblies = new HashSet<string>();
try
{
// 核心程序集列表
var coreAssemblies = new[]
{
typeof(object), // System.Private.CoreLib
typeof(Console), // System.Console
typeof(Control), // System.Windows.Forms
typeof(MessageBox), // System.Windows.Forms
typeof(System.Drawing.Color), // System.Drawing
typeof(System.Drawing.Point), // System.Drawing.Primitives
typeof(Dictionary<,>), // System.Collections
typeof(Enumerable), // System.Linq
typeof(System.ComponentModel.Component), // System.ComponentModel.Primitives
typeof(System.ComponentModel.TypeConverter), // System.ComponentModel.TypeConverter
typeof(Encoding), // System.Text.Encoding.Extensions
typeof(System.Text.RegularExpressions.Regex) // System.Text.RegularExpressions
};
// 添加核心程序集
foreach (var type in coreAssemblies)
{
try
{
var location = type.Assembly.Location;
if (!string.IsNullOrEmpty(location) && File.Exists(location) && !addedAssemblies.Contains(location))
{
references.Add(MetadataReference.CreateFromFile(location));
addedAssemblies.Add(location);
}
}
catch { }
}
// 添加当前程序集
var currentAssembly = Assembly.GetExecutingAssembly();
if (!string.IsNullOrEmpty(currentAssembly.Location) && !addedAssemblies.Contains(currentAssembly.Location))
{
references.Add(MetadataReference.CreateFromFile(currentAssembly.Location));
addedAssemblies.Add(currentAssembly.Location);
}
// 尝试通过名称加载必要的程序集
var requiredAssemblyNames = new[]
{
"System.Runtime",
"System.Private.CoreLib",
"mscorlib",
"System.ComponentModel.Primitives",
"System.ComponentModel.TypeConverter",
"System.ComponentModel",
"System.Drawing.Primitives",
"System.Collections",
"System.Collections.Concurrent",
"System.Text.Encoding.Extensions",
"System.Text.RegularExpressions",
"netstandard"
};
foreach (var assemblyName in requiredAssemblyNames)
{
try
{
var assembly = Assembly.Load(assemblyName);
var location = assembly.Location;
if (!string.IsNullOrEmpty(location) && File.Exists(location) && !addedAssemblies.Contains(location))
{
references.Add(MetadataReference.CreateFromFile(location));
addedAssemblies.Add(location);
}
}
catch { }
}
// 从当前 AppDomain 加载的程序集中查找
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
try
{
if (!assembly.IsDynamic &&
!string.IsNullOrEmpty(assembly.Location) &&
File.Exists(assembly.Location) &&
!addedAssemblies.Contains(assembly.Location))
{
var name = assembly.GetName().Name;
if (name.StartsWith("System.") ||
name.StartsWith("Microsoft.") ||
name.Equals("mscorlib") ||
name.Equals("netstandard"))
{
references.Add(MetadataReference.CreateFromFile(assembly.Location));
addedAssemblies.Add(assembly.Location);
}
}
}
catch { }
}
Console.WriteLine($"Added {references.Count} assembly references for script compilation.");
}
catch (Exception ex)
{
Console.WriteLine($"Error getting metadata references: {ex.Message}");
// 最小引用集作为后备
references.Clear();
addedAssemblies.Clear();
var fallbackAssemblies = new[]
{
typeof(object).Assembly.Location,
typeof(Control).Assembly.Location,
typeof(MessageBox).Assembly.Location
};
foreach (var location in fallbackAssemblies)
{
if (!string.IsNullOrEmpty(location) && File.Exists(location))
{
references.Add(MetadataReference.CreateFromFile(location));
}
}
}
return references.ToArray();
}
public void ExecuteScript(string scriptId, Control sender, EventArgs e)
{
if (_compiledScripts.TryGetValue(scriptId, out var assembly))
{
try
{
var type = assembly.GetType("ScriptClass");
if (type == null)
{
MessageBox.Show("无法找到脚本类", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
var instance = Activator.CreateInstance(type);
// 设置控件字典
if (_controlManager != null)
{
var controlDict = new Dictionary<string, Control>();
foreach (var kvp in _controlManager.ControlsByName)
{
controlDict[kvp.Key] = kvp.Value.InnerControl;
}
var setControlsMethod = type.GetMethod("SetControls");
setControlsMethod?.Invoke(instance, new object[] { controlDict });
}
var method = type.GetMethod("Execute");
if (method == null)
{
MessageBox.Show("无法找到Execute方法", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
method.Invoke(instance, new object[] { sender, e });
}
catch (Exception ex)
{
MessageBox.Show($"脚本执行错误: {ex.Message}\n\n详细信息:\n{ex.StackTrace}",
"错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show($"未找到脚本: {scriptId}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
// 清理编译缓存的方法
public void ClearCompiledScripts()
{
_compiledScripts.Clear();
}
// 获取所有已编译脚本的ID
public IEnumerable<string> GetCompiledScriptIds()
{
return _compiledScripts.Keys;
}
// 测试编译功能
public bool TestCompilation(out string error)
{
var testCode = @"MessageBox.Show(""Test compilation successful!"");";
return CompileScript("test", testCode, out error);
}
}
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。