我想知道是否可以编译和运行存储的代码,而无需生成 exe 或任何类型的其他文件,基本上是从内存中运行文件。
基本上,主应用程序将有一些存储的代码(可能会更改的代码),它需要编译代码并执行它。无需创建任何文件。
创建文件,运行程序,然后删除文件不是一种选择。编译后的代码需要从内存中运行。
代码示例,指针,或几乎任何东西都是受欢迎的:)
我想知道是否可以编译和运行存储的代码,而无需生成 exe 或任何类型的其他文件,基本上是从内存中运行文件。
基本上,主应用程序将有一些存储的代码(可能会更改的代码),它需要编译代码并执行它。无需创建任何文件。
创建文件,运行程序,然后删除文件不是一种选择。编译后的代码需要从内存中运行。
代码示例,指针,或几乎任何东西都是受欢迎的:)
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[] { });
}
这会从包含的源代码字符串编译一个简单的类,然后实例化该类并在其上反射调用一个函数。
这是一个如何使用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;
}
这是可能的。它是容易还是难,取决于你想写多少和什么样的代码。
System.Linq.Expressions
直截了当但有限)System.Reflection.Emit
很难调试,但并非不可能)编辑:请注意,在 .NET 4.0 之前,System.Linq.Expressions
仅限于您可以在 C# 的单行上放置的内容:即没有 if、while、变量赋值等。
是的,你可以这样做。这很慢,但你当然可以做到。查看 CodeDOM 或(new CSharpCodeProvider().CreateCompiler())
.Net 中的。
调查System.CodeDom
。它将完全满足您的需求。
在 Mono 中,您使用 CSharp.Evaluator。它在内存中真正起作用。提到的其他一些解决方案在引擎盖下的文件中写出和读回。
还可以看看嵌入脚本语言,如 Python、Ruby、Lua 等。所有这些都支持从内存执行代码,而无需将任何内容写入磁盘。
在不创建文件的情况下编译和执行 C# 是很困难的,如果不是不可能的话,因为……嗯,这就是编译的意义——将语言变成可执行文件。您正在寻找的是某种脚本功能。您在问题中描述的本质上是解释语言和编译语言之间的区别。请参阅维基百科:脚本语言。
根据您将使用此功能的目的,您可以充分利用 Python、Ruby 或 Lua 等脚本语言。这是一个示例:如何从 C# 运行 Python 脚本?
这将使您的应用程序依赖于 python.exe(或运行您选择的脚本语言所需的任何可执行文件)。如果您想避免这种情况,根据您需要对注入的脚本执行的操作,制作您自己的脚本语言供您的应用程序执行运行时可能并不难。
编辑:第一段是垃圾。对不起。请参阅http://msdn.microsoft.com/en-us/library/8ffc3x75%28v=vs.110%29.aspx