English 中文(简体)
Is it possible to save a dynamic assembly to disk?
原标题:

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 ~LocalSettingsTemp 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.

最佳回答

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

问题回答

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

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.

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




相关问题
Manually implementing high performance algorithms in .NET

As a learning experience I recently tried implementing Quicksort with 3 way partitioning in C#. Apart from needing to add an extra range check on the left/right variables before the recursive call, ...

Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

How do I compare two decimals to 10 decimal places?

I m using decimal type (.net), and I want to see if two numbers are equal. But I only want to be accurate to 10 decimal places. For example take these three numbers. I want them all to be equal. 0....

Exception practices when creating a SynchronizationContext?

I m creating an STA version of the SynchronizationContext for use in Windows Workflow 4.0. I m wondering what to do about exceptions when Post-ing callbacks. The SynchronizationContext can be used ...

Show running instance in single instance application

I am building an application with C#. I managed to turn this into a single instance application by checking if the same process is already running. Process[] pname = Process.GetProcessesByName("...

How to combine DataTrigger and EventTrigger?

NOTE I have asked the related question (with an accepted answer): How to combine DataTrigger and Trigger? I think I need to combine an EventTrigger and a DataTrigger to achieve what I m after: when ...

热门标签