Is it possible to save a dynamic assembly to disk?

回眸只為那壹抹淺笑 提交于 2019-11-30 23:27:25

问题


I recently bought Ayende's book Building DSLs in Boo (buy it, read it, it's awesome) but I'm coming up against an implementation problem and I want to see what the generated code looks like. I would normally use reflector to look at the code but in this case the assemblies are dynamic and only in memory. Is there a way to save dynamic assemblies to disk so that I can reflect them?

EDIT / My Answer:

Wow, it took awhile to come back to this one. Unfortunately I left an important bit out from the original question.

Important Bit: I'm using Ayende's RhinoDSL library as he recommends in the book. I have access to the boo compiler in my subclass of DslEngine which looks like this:

public class JobEngine : DslEngine
{
    protected override void CustomizeCompiler(Boo.Lang.Compiler.BooCompiler compiler, Boo.Lang.Compiler.CompilerPipeline pipeline, string[] urls)
    {
        pipeline.Insert(1, new ImplicitBaseClassCompilerStep(typeof (JobBase), "Prepare", "JobLanguage", "log4net", "Quartz"));
    }
}

To change the least and get what I wanted I needed to add one line...

public class JobEngine : DslEngine
{
    protected override void CustomizeCompiler(Boo.Lang.Compiler.BooCompiler compiler, Boo.Lang.Compiler.CompilerPipeline pipeline, string[] urls)
    {
        compiler.Parameters.GenerateInMemory = false; // <--- This one.
        pipeline.Insert(1, new ImplicitBaseClassCompilerStep(typeof (JobBase), "Prepare", "JobLanguage", "log4net", "Quartz"));
    }
}

This caused the compiler to output the assembly to my ~\LocalSettings\Temp directory and then I could then reflect it. It's important to note that making that change caused the rest of the program to break (RhinoDSL could no longer find the assemblies in memory because I output them to disk), so this is only useful as a debugging tool.


回答1:


Look up where BooCompiler is instantiated, change the pipeline from CompileToMemory to CompileToFile




回答2:


Yes, the AssemblyBuilder class has a Save method for this purpose. You need to use the appropriate mode for this, which is most likely RunAndSave:

AssemblyBuilder builder =
    AppDomain.CurrentDomain.DefineDynamicAssembly(
        name, AssemblyBuilderAccess.RunAndSave);
// build assembly
builder.Save(path);



回答3:


If you can get the Assembly at runtime.

i.e.

Assembly assembly = typeof(YourDynamicType).Assembly;

You can then cast this assembly into AssemblyBuilder and call the Save method.

AssemblyBuilder assemblyBuilder = (AssemblyBuilder)assembly;
assemblyBuilder.Save(yourPath);



回答4:


There may be an easier way to do it, but if you don't mind using WinDbg you can save any loaded managed assembly from memory (WinDbg uses the term module, but it works for managed assemblies as well).

Use the !savemodule command with the address of the assembly. If you don't have the address use the lm vm command with the module name. Following that you get a regular DLL assembly, that you can inspect in Reflector.

Of course you may also just look at the IL code in memory.



来源:https://stackoverflow.com/questions/2058340/is-it-possible-to-save-a-dynamic-assembly-to-disk

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!