3
在我投入大量時間瞭解roslyn編譯器服務之前,我想問問下列情況是否適用於roslyn。是否有可能編譯程序集而不必將任何內容寫入磁盤並執行它?我基於元模型生成完整的解決方案,並且我想要將它編譯並執行它。 Roslyn可能嗎?Roslyn:從元模型創建程序集
在我投入大量時間瞭解roslyn編譯器服務之前,我想問問下列情況是否適用於roslyn。是否有可能編譯程序集而不必將任何內容寫入磁盤並執行它?我基於元模型生成完整的解決方案,並且我想要將它編譯並執行它。 Roslyn可能嗎?Roslyn:從元模型創建程序集
是的。我自己在做這個。這裏是如何做到這一點的例子:
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;
}
這裏有一個稍微更輕的版本:
// 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());
}
爲什麼很重要,你不寫什麼盤? – svick
@svick:沒有試圖粗魯或任何事情,但爲了回答這個問題,爲什麼重要的是不要寫任何東西到磁盤上並不重要。 – epitka
這可能沒有關係,但很難判斷你是否不告訴我們。很多時候,人們會陷入[XY問題](http://meta.stackexchange.com/q/66377/130186):不問實際的問題。因此,如果你清楚地說明*你實際上正在努力做什麼,而不僅僅是*你想要做什麼,這會有所幫助。 – svick