编译并运行动态代码,而不生成EXE?

时间:2010-07-06 17:57:03

标签: c# runtime-compilation

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

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

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

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

8 个答案:

答案 0 :(得分:35)

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[] { });
}

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

答案 1 :(得分:5)

以下是如何使用System.Linq.Expressions添加到Tim的答案的示例。显然它不是最漂亮的代码,但是以这种漂亮的树状形式使它变得如此简单。

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;
}

答案 2 :(得分:4)

这是可能的。这很容易或很难,取决于你想要编写多少代码和什么类型的代码。

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

答案 3 :(得分:1)

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

答案 4 :(得分:1)

查看System.CodeDom。它将完全符合您的要求。

答案 5 :(得分:0)

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

答案 6 :(得分:-1)

另外看一下嵌入Python,Ruby,Lua等脚本语言。所有这些都支持从内存中执行代码而不会将任何内容写入磁盘。

答案 7 :(得分:-2)

如果不是不可能的话,在没有创建文件的情况下编译和执行C#是很困难的,因为......好吧,那就是汇编 - 将语言变成可执行文件。您正在寻找的是某种脚本功能。您在问题中描述的内容基本上是解释语言与编译语言之间的区别。见Wikipedia: Scripting language

根据您将使用此功能的内容,您可以充分利用Python,Ruby或Lua等脚本语言。这是一个例子:How do I run a Python script from C#?

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

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