在我投入大量时间学习 roslyn 编译器服务之前,我想问一下 roslyn 是否可以实现以下场景。是否可以编译程序集而无需将任何内容写入磁盘并执行它?我基于元模型生成完整的解决方案,我想接受它并编译它并执行它。罗斯林有可能吗?
问问题
826 次
2 回答
3
这是一个稍微轻一点的版本:
// Some standard references most projects use
var references = new List<MetadataReference>
{
MetadataReference.CreateAssemblyReference("mscorlib"),
MetadataReference.CreateAssemblyReference("System"),
MetadataReference.CreateAssemblyReference("System.Linq"),
new MetadataFileReference(this.GetType().Assembly.Location)
};
// The MyClassInAString is where your code goes
var syntaxTree = SyntaxTree.ParseText(MyClassInAString);
// Use Roslyn to compile the code into a DLL
var compiledCode = Compilation.Create(
"MyAssemblyName",
options: new CompilationOptions(OutputKind.DynamicallyLinkedLibrary),
syntaxTrees: syntaxTree,
references: references;
);
// Now read the code into a memory stream. You can then load types out of the assembly with reflection
Assembly assembly;
using (var stream = new MemoryStream())
{
EmitResult compileResult = compiledCode.Emit(stream);
if (!compileResult.Success)
{
throw new InvalidOperationException("The assembly could not be built, there are {0} diagnostic messages.".FormatWith(compileResult.Diagnostics.Count()));
}
assembly = Assembly.Load(stream.GetBuffer());
}
于 2014-01-30T16:04:06.790 回答
1
Yes. I am doing this myself. Here is a sample on how to do it:
public void CompileCode(programString){
// Now that we have a compiled program we can actually compile it...
// Program parsing code...
SyntaxTree programSyntaxTree =
SyntaxTree.ParseText(programString);
const string name = "CompiledProgram.dll";
var compilation = Compilation.Create(name,
options: new CompilationOptions(OutputKind.DynamicallyLinkedLibrary),
syntaxTrees: new[] {
programSyntaxTree
},
references: new[]{
new MetadataFileReference(typeof(object).Assembly.Location)
}
);
var modBuilder = BuildModuleBuilder();
ReflectionEmitResult result = compilation.Emit(modBuilder);
foreach (Diagnostic c in result.Diagnostics) {
Console.WriteLine("D: {0}", c.ToString());
}
if (result.Diagnostics.LongCount() > 0) return false;
this.builtModule = modBuilder;
}
private ModuleBuilder BuildModuleBuilder() {
// Get the current application domain for the current thread.
var currentDomain = AppDomain.CurrentDomain;
var assemblyName = new AssemblyName {Name = "TempAssembly"};
// Define a dynamic assembly in the current application domain.
this.assemblyBuilder = currentDomain.DefineDynamicAssembly(
assemblyName,
AssemblyBuilderAccess.RunAndCollect
);
// Define a dynamic module in this assembly.
var moduleBuilder = this.assemblyBuilder.DefineDynamicModule("TempModule");
return moduleBuilder;
}
public Delegate RunCompiledProgram() {
if (this.builtModule == null) return null;
var type = this.builtModule.GetType("ProgramCompiler.BuiltProgram");
var methodInfo = type.GetMethod("Eval");
object o = Activator.CreateInstance(type, null, null);
Delegate test = (BuiltProg) Delegate.CreateDelegate(
typeof(BuiltProg), o, methodInfo, false
);
return test;
}
于 2013-07-17T19:09:54.443 回答