这篇文章主要介绍C#中如何实现代码解释器,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
1、C#代码解释器简介
能够动态执行 C#代码是一件很酷的功能,比如,我们可以在控制台中输入一行 C#代码,然后程序自动编译并执行这一行代码,将结果显示给我们。这差不多就是一个最简单的 C#代码解释器了。
动态执行 C#代码又是一件很有用的功能,比如,我们可以将某些代码写在某个文件之中,由程序集在执行时进行加载,改变这些代码不用中止程序,当程序再次加载这些代码时,就自动执行的是新代码了。
2、简单的 C#代码解释器
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Reflection;
usingSystem.Globalization;
usingMicrosoft.CSharp;
usingSystem.CodeDom;
usingSystem.CodeDom.Compiler;
usingSystem.Text;
usingSystem.IO;
usingSystem.Xml;
namespaceTest
{
classProgram
{
staticvoidMain(string[]args)
{
Console.Write(">>");
Stringcmd;
Contextcxt=newContext();
while((cmd=Console.ReadLine().Trim())!="exit")
{
if(!String.IsNullOrEmpty(cmd))
{
Console.WriteLine();
cxt.Invoke(cmd);
}
Console.Write("/n>>");
}
}
}
publicclassContext
{
publicCSharpCodeProviderCodeProvider{get;set;}
publicIDictionary<String,Assembly>Assemblys{get;set;}
publicContext()
{
CodeProvider=newCSharpCodeProvider(newDictionary<string,string>()
{{"CompilerVersion","v3.5"}});Assemblys=newDictionary<String,Assembly>();
Assembly[]al=AppDomain.CurrentDomain.GetAssemblies();
foreach(Assemblyainal)
{
AddAssembly(a);
}
AppDomain.CurrentDomain.AssemblyLoad+=newAssemblyLoadEventHandler
(CurrentDomain_AssemblyLoad);}
privatevoidAddAssembly(Assemblya)
{
if(a!=null)
{
Assemblys.Add(a.FullName,a);
}
}
voidCurrentDomain_AssemblyLoad(objectsender,AssemblyLoadEventArgsargs)
{
Assemblya=args.LoadedAssembly;
if(!Assemblys.ContainsKey(a.FullName))
{
AddAssembly(a);
}
}
publicCompilerParametersCreateCompilerParameters()
{
CompilerParameterscp=newCompilerParameters();
cp.GenerateExecutable=false;
cp.GenerateInMemory=true;
if(Assemblys!=null)
{
foreach(AssemblyainAssemblys.Values)
{
cp.ReferencedAssemblies.Add(a.Location);
}
}
returncp;
}
publicvoidInvoke(Stringcmd)
{
StringinputCmdString=cmd.Trim();
if(String.IsNullOrEmpty(inputCmdString))return;
StringfullCmd=BuildFullCmd(inputCmdString);
CompilerResultscr=CodeProvider.CompileAssemblyFromSource
(CreateCompilerParameters(),fullCmd);
if(cr.Errors.HasErrors)
{
BooleanrecompileSwitch=true;
foreach(CompilerErrorerrincr.Errors)
{
//CS0201:Onlyassignment,call,increment,decrement,andnewobjectexpressionscanbe
//usedasastatement
if(!err.ErrorNumber.Equals("CS0201"))
{
recompileSwitch=false;
break;
}
}
//重新编译
if(recompileSwitch)
{
StringdynaName="TempArg_Dynamic_"+DateTime.Now.Ticks.ToString();
inputCmdString=String.Format("var{0}=",dynaName)+inputCmdString;
inputCmdString+=";/nSystem.Console.WriteLine("+dynaName+");";
fullCmd=BuildFullCmd(inputCmdString);
cr=CodeProvider.CompileAssemblyFromSource(CreateCompilerParameters(),fullCmd);
}
if(cr.Errors.HasErrors)
{
Console.WriteLine("编译错误:");
foreach(CompilerErrorerrincr.Errors)
{
Console.WriteLine(err.ErrorNumber);
Console.WriteLine(err.ErrorText);
}
return;
}
}
Assemblyassem=cr.CompiledAssembly;
ObjectdynamicObject=assem.CreateInstance("Test.DynamicClass");
Typet=assem.GetType("Test.DynamicClass");
MethodInfominfo=t.GetMethod("MethodInstance");
minfo.Invoke(dynamicObject,null);
}
privateStringBuildFullCmd(StringinputCmdString)
{
StringStringfullCmd=String.Empty;
fullCmd+=@"
namespaceTest
{
publicclassDynamicClass
{
publicvoidMethodInstance()
{
"+inputCmdString+@";
}
}
}";
returnfullCmd;
}
}
}
以上是“C#中如何实现代码解释器”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!
原创文章,作者:506227337,如若转载,请注明出处:https://blog.ytso.com/tech/dev/230737.html