您好,登錄后才能下訂單哦!
這篇文章主要介紹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#中如何實現代碼解釋器”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。