最近在研究给自己的C#程序开放简单的脚本扩展能力,原因是在某些业务,需要技术人员灵活变动一些程序内容。查找资料后找到了C#支持的动态编译能力CSharpCodeProvider
,它能将用户编写的脚本动态编译成dll,以此实现C#程序的动态脚本支持。
看不懂没关系,文末有完成源码。
核心代码如下:
复制
public object PreviewRun(dynamic inputObject, out string mes) { CSharpCodeProvider cSharpCodePrivoder = new CSharpCodeProvider(); StringBuilder stringBuilder = new StringBuilder(); CompilerParameters objCompilerParameters = new CompilerParameters(); objCompilerParameters.ReferencedAssemblies.Add("System.dll"); objCompilerParameters.ReferencedAssemblies.Add("Microsoft.CSharp.dll"); objCompilerParameters.ReferencedAssemblies.Add("System.Core.dll"); objCompilerParameters.ReferencedAssemblies.Add("System.Data.dll"); objCompilerParameters.ReferencedAssemblies.Add("System.Net.Http.dll"); objCompilerParameters.ReferencedAssemblies.Add("System.Xml.dll"); objCompilerParameters.ReferencedAssemblies.Add("System.Xml.Linq.dll"); objCompilerParameters.GenerateExecutable = false; objCompilerParameters.GenerateInMemory = true; var compilerResults = cSharpCodePrivoder.CompileAssemblyFromSource(objCompilerParameters, sources); if (compilerResults.Errors.HasErrors) { stringBuilder.AppendLine("脚本错误:"); foreach (CompilerError err in compilerResults.Errors) { stringBuilder.AppendLine(err.ErrorText); } mes = stringBuilder.ToString(); return null; } else { mes = null; try { var asm = compilerResults.CompiledAssembly.CreateInstance("DMD"); MethodInfo method = asm.GetType().GetMethod("Main"); return method.Invoke(asm, new object[] { inputObject }); } catch (TargetInvocationException ex) { mes = ex.InnerException.Message; return null; } } }
测试脚本:
复制
using System; using System.Runtime.CompilerServices; public class DMD { public static string Main(dynamic input) { input.move(1,2,3); Console.WriteLine(input.Age); Console.WriteLine(input.Name); return "okkkk"; } }
给自己的C#程序上加入动态编译脚本的能力,可以让程序内容更完善,当然也可能让你的程序漏洞更多。我这次的项目设计到用户经常修改运动轨迹,所以需要将运动点位这部分内容的编辑能力提供给客户。虽然不使用动态编译脚本的功能也能实现此功能,但是实现起来太复杂了,我才不干,都交给客户自己完成,给予客户更高的自由度!
评论 (0)