能否在运行时解析和评估.NET代码?

3

我觉得如果我能够在运行时编写vb.net或c#代码,并且解释器可以像python一样自动解析它,那将会很有趣,因此我制作了一个类似的小程序。基本上它看起来像这样:

InputArgs = Console.ReadLine()
ParseInput(InputArgs.Split(" "))

Private Sub ParseInput(Args as List(Of String), Optional TempArgs as List(Of String))
Dim arg as string = Args(0)
If arg = ".." then
 ...
elseif arg = ".." then
 ...
end if
End Sub

我知道这不是一个好的系统,但它展示了基础知识。所以我的问题是:能否使vb.net或c#像python一样在运行时解释?


1
你可以使用新的Rosyln CTP来完成这个任务。 - Prescott
如果你认为这是不可能的,那么你认为造成这种情况的原因是什么?在程序员的世界里,几乎可以做任何事情,但有些事情并不容易实现。无论如何,请看Roslyn - Snowbear
2
看看这个问题:https://dev59.com/pXVD5IYBdhLWcg3wWaVh - hcb
工作流引擎(WF4)具有VB表达式求值器。它只支持VB和表达式,而且我不知道它是否可以在WF之外使用,但您可能能够使其适用于您的情况。 - Gabe
6个回答

5
这个已经以多种形式出现了:

Mono.CSharp

Mono.CSharp程序集是Mono中的一种工具,你可以引用它来执行CSharp.exe(一个C# "解释器"或交互式shell)所能做的任何事情:

void ReadEvalPrintLoopWith (ReadLiner readline)
{
    string expr = null;
    while (!InteractiveBase.QuitRequested){
            string input = readline (expr == null);
            if (input == null)
                return;

            if (input == "")
                continue;

            expr = expr == null ? input : expr + "\n" + input;

            expr = Evaluate (expr);
    } 
}

不用说,这也适用于MS.Net(当然,这就是可移植的.Net的重点)。
完整的源代码可以在github上找到 - 实际上,与Mono的其余部分一样。

DLR

已经实现了几种DLR语言,包括但不限于: 它将允许您在.NET框架中即时评估Python/Ruby代码。

Roslyn

微软已经将Roslyn发布为CTP(预览版)。它基本上可以像Mono REPL(第一项)一样做同样的事情,而且(更多)。但它仍然是一个预览版。

2

1

你是在重新发明 LinqPad 吗?

LinqPad 是一个免费的人体工学 C#/VB/F# scratchpad,它可以立即执行任何表达式、语句块或程序,并具有丰富的输出格式。它非常优秀。

如果你真的想要开发自己的工具,请看看一些类似的现有问题 one two three four...


1

抱歉没有太多时间给你一个恰当的答案,但这里是我旧项目中的 eval 代码:

        CSharpCodeProvider c = new CSharpCodeProvider();
        ICodeCompiler icc = c.CreateCompiler();
        CompilerParameters cp = new CompilerParameters();

        cp.ReferencedAssemblies.Add("system.dll");
        cp.ReferencedAssemblies.Add("system.xml.dll");
        cp.ReferencedAssemblies.Add("system.data.dll");
        cp.ReferencedAssemblies.Add("system.windows.forms.dll");
        cp.ReferencedAssemblies.Add("system.drawing.dll");

        cp.CompilerOptions = "/t:library";
        cp.GenerateInMemory = true;

        StringBuilder sb = new StringBuilder("");
        sb.Append("using System;\n");
        sb.Append("using System.Xml;\n");
        sb.Append("using System.Data;\n");
        sb.Append("using System.Data.SqlClient;\n");
        sb.Append("using System.Windows.Forms;\n");
        sb.Append("using System.Drawing;\n");

        sb.Append("namespace CSCodeEvaler{ \n");
        sb.Append("public class CSCodeEvaler{ " + csCode + "} }");

        CompilerResults cr = icc.CompileAssemblyFromSource(cp, sb.ToString());
        if (cr.Errors.Count > 0)
        {
            MessageBox.Show("ERROR: " + cr.Errors[0].ErrorText,
               "Error evaluating cs code", MessageBoxButtons.OK,
               MessageBoxIcon.Error);
            return null;
        }

        System.Reflection.Assembly a = cr.CompiledAssembly;
        object o = a.CreateInstance("CSCodeEvaler.CSCodeEvaler");

        Type t = o.GetType();
        MethodInfo mi = t.GetMethod("Transform");

        return mi;

该代码的原始变体来源于:http://www.codeproject.com/KB/cs/evalcscode.aspx

它编译一些 C# 代码(代码应该在 csCode 变量中),然后尝试在其中找到 Transform() 方法并返回其 MethodInfo,以便我们可以执行它。

但请记住,每次调用此代码都会加载一个新程序集,因此不要过于频繁地使用它。

另外,正如 Prescott 所说- 尝试使用 Roslyn。

希望这可以帮到您。很抱歉没有提供更具体的与您问题相关的代码示例。

附注:如果您想要一些交互式窗口,则有第三方控件可用(使用谷歌搜索以查找,因为我不记得确切的产品名称)。


0

我不是很清楚,但你可以通过创建一个带有TextChanged事件处理程序的文本区域来调用编译器程序(不确定在哪里)。


调用编译器是无济于事的,因为解释代码通常无法编译。 - Snowbear

-1
所以我的问题是:是否可能使vb.net或c#像Python一样在运行时解释?
当然可以。开始编写一个解释器,然后您就可以解释它了。 从一个漂亮的语法解析器开始。然后继续前进。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接