22

我想知道是否可以编译和运行存储的代码,而无需生成 exe 或任何类型的其他文件,基本上是从内存中运行文件。

基本上,主应用程序将有一些存储的代码(可能会更改的代码),它需要编译代码并执行它。无需创建任何文件。

创建文件,运行程序,然后删除文件不是一种选择。编译后的代码需要从内存中运行。

代码示例,指针,或几乎任何东西都是受欢迎的:)

4

8 回答 8

36
using (Microsoft.CSharp.CSharpCodeProvider foo = 
           new Microsoft.CSharp.CSharpCodeProvider())
{
    var res = foo.CompileAssemblyFromSource(
        new System.CodeDom.Compiler.CompilerParameters() 
        {  
            GenerateInMemory = true 
        }, 
        "public class FooClass { public string Execute() { return \"output!\";}}"
    );

    var type = res.CompiledAssembly.GetType("FooClass");

    var obj = Activator.CreateInstance(type);

    var output = type.GetMethod("Execute").Invoke(obj, new object[] { });
}

这会从包含的源代码字符串编译一个简单的类,然后实例化该类并在其上反射调用一个函数。

于 2010-07-06T18:08:56.957 回答
5

这是一个如何使用System.Linq.Expressions添加到蒂姆的答案的示例。显然它不是最漂亮的代码,但是以这种漂亮的树状形式拥有它使开发变得如此容易。

private  Expression<IsWordChar> CreateIsWordCharExpression()
{
    var e = Expression.Parameter(typeof(int), "e");
    var c = Expression.Variable(typeof(char), "c");
    var returnLabel = Expression.Label(Expression.Label(typeof(bool)), _falseConstant);
    var lambda = Expression.Lambda<IsWordChar>(
        Expression.Block(
            new[] { c },
            Expression.IfThen(
                Expression.OrElse(
                    Expression.Equal(e, Expression.Constant(-1)),
                    Expression.Equal(e, _inputLengthVar)
                ),
                Expression.Return(returnLabel.Target, _falseConstant)
            ),
            Expression.Assign(c, Expression.MakeIndex(_str, _stringCharsPropertyInfo, new[] { e })),
            Expression.IfThenElse(
                Expression.OrElse(
                    Expression.OrElse(
                        Expression.OrElse(
                            Expression.AndAlso(
                                Expression.GreaterThanOrEqual(c, Expression.Constant('a')),
                                Expression.LessThanOrEqual(c, Expression.Constant('z'))
                            ),
                            Expression.AndAlso(
                                Expression.GreaterThanOrEqual(c, Expression.Constant('A')),
                                Expression.LessThanOrEqual(c, Expression.Constant('Z'))
                            )
                        ),
                        Expression.AndAlso(
                            Expression.GreaterThanOrEqual(c, Expression.Constant('0')),
                            Expression.LessThanOrEqual(c, Expression.Constant('1'))
                        )
                    ),
                    Expression.Equal(c, Expression.Constant('_'))
                ),
                Expression.Return(returnLabel.Target, _trueConstant),
                Expression.Return(returnLabel.Target, _falseConstant)
            ),
            returnLabel
        ),
        "IsWordChar",
        new[] { e }
    );
    return lambda;
}
于 2010-07-06T18:21:08.477 回答
4

这是可能的。它是容易还是难,取决于你想写多少和什么样的代码。

编辑:请注意,在 .NET 4.0 之前,System.Linq.Expressions仅限于您可以在 C# 的单行上放置的内容:即没有 if、while、变量赋值等。

于 2010-07-06T18:00:09.767 回答
2

是的,你可以这样做。这很慢,但你当然可以做到。查看 CodeDOM 或(new CSharpCodeProvider().CreateCompiler()).Net 中的。

于 2010-07-06T17:59:10.763 回答
1

调查System.CodeDom。它将完全满足您的需求。

于 2010-07-06T17:59:35.353 回答
0

在 Mono 中,您使用 CSharp.Evaluator。它在内存中真正起作用。提到的其他一些解决方案在引擎盖下的文件中写出和读回。

于 2014-11-10T22:26:12.377 回答
-1

还可以看看嵌入脚本语言,如 Python、Ruby、Lua 等。所有这些都支持从内存执行代码,而无需将任何内容写入磁盘。

于 2010-07-06T18:11:22.893 回答
-2

在不创建文件的情况下编译和执行 C# 是很困难的,如果不是不可能的话,因为……嗯,这就是编译的意义——将语言变成可执行文件。您正在寻找的是某种脚本功能。您在问题中描述的本质上是解释语言和编译语言之间的区别。请参阅维基百科:脚本语言

根据您将使用此功能的目的,您可以充分利用 Python、Ruby 或 Lua 等脚本语言。这是一个示例:如何从 C# 运行 Python 脚本?

这将使您的应用程序依赖于 python.exe(或运行您选择的脚本语言所需的任何可执行文件)。如果您想避免这种情况,根据您需要对注入的脚本执行的操作,制作您自己的脚本语言供您的应用程序执行运行时可能并不难。

编辑:第一段是垃圾。对不起。请参阅http://msdn.microsoft.com/en-us/library/8ffc3x75%28v=vs.110%29.aspx

于 2014-02-19T05:19:29.357 回答