动态编译和执行C#脚本
参数 | 说明 |
---|---|
code | 要编译的脚本 |
function | 需要执行的方法 |
invoker | 成功编译后的执行器 |
matcher | 方法完整匹配(非必须) |
脚本
public string Format(string year)
{
var x = new System.Text.StringBuilder(200);
var t = new System.DateTime();
//var s = $"{year}--name";
var s = string.Format("{0}--name", year);
return s;
}
执行
if (TryCompile(doc, "Format", out var invoker,
"System.String Format(System.String)"))
{
var res = invoker.Invoke(new object[] { "2018902-02" });
Console.WriteLine(res);
}
输出
2018902-02--name
public bool TryCompile(string code, string function, out Func<object[], object> invoker, string matcher = null)
{
invoker = null;
if (string.IsNullOrEmpty(code)) return false;
if (!code.Contains(function)) return false;
const string _name = "_TempScript";
StringBuilder builder = new StringBuilder(code.Length + 20);
builder.AppendLine("using System;");
builder.AppendLine("namespace _tempNamespace{");
builder.Append($"class {_name}");
builder.AppendLine("{");
builder.AppendLine(code);
builder.AppendLine("}}");
using (CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp"))
{
CompilerParameters option = new CompilerParameters
{
GenerateExecutable = false,
GenerateInMemory = true,
TreatWarningsAsErrors = false,
IncludeDebugInformation = false,
OutputAssembly = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, _name + ".tmp")
};
CompilerResults cr = provider.CompileAssemblyFromSource(option, new string[] { builder.ToString() });
if (cr.Errors.HasErrors)
{
Console.WriteLine("编译错误:");
foreach (CompilerError err in cr.Errors)
Console.WriteLine(err.ErrorText);
return false;
}
Assembly _assembly = cr.CompiledAssembly;
TypeInfo _type;
using (var e = _assembly.DefinedTypes.GetEnumerator())
{
e.MoveNext();
_type = e.Current;
}
MethodInfo _method = _type.GetMethod(function);
if (_method == null) { Console.WriteLine("未找到指定方法"); return false; }
if (matcher != null && !matcher.Equals(_method.ToString(), StringComparison.OrdinalIgnoreCase))
{ Console.WriteLine("指定方法结构与预期不一致"); return false; }
var obj = Activator.CreateInstance(_type);
invoker = (parameters) => _method.Invoke(obj, parameters);
return true;
}
}