Learn Roslyn Now: Part 16 The Emit API

Up until now, we’ve mostly looked at how we can use Roslyn to analyze and manipulate source code. Now we’ll take a look at finishing the compilation process by emitting it disk or to memory. To start, we’ll just try emitting a simple compilation to disk and checking whether or not it succeeded.

After running this code we can see that our executable and .pdb have been emitted to Debug/bin/. We can double click output.exe and see that our program runs as expected. Keep in mind that the .pdb file is optional. I’ve only chosen to emit it here to show off the API. Writing the .pdb file to disk can take a fairly long time and it often pays to omit this argument unless you really need it.

Sometimes we might not want to emit to disk. We might just want to compile the code, emit it to memory and then execute it from memory. Keep in mind that for most cases where we’d want to do this, the scripting API probably makes more sense to use. Still, it pays to know our options.

Finally, what if we want to influence  how our code is compiled? We might want to allow unsafe code, mark warnings as errors or delay sign the assembly. All of these options can be customized by passing a CSharpCompilationOptions object to CSharpCompilation.Create(). We’ll take a look at how we can interact with a few of these properties below.

In total there are about twenty-five different options available for customization. Basically any option you have within the Visual Studio’s project property page should be available here.

Advanced options

There are a few optional parameters available in Compilation.Emit() that are worth discussing. Some of them I’m familiar with, but others I’ve never used.

  • xmlDocPath – Auto generates XML documentation based on the documentation comments present on your classes, methods, properties etc.
  • manifestResources – Allows you to manually embed resources such as strings and images within the emitted assembly. Batteries are not included with this API and it requires some heavy lifting if you want to embed .resx resources within your assembly. We’ll explore this overload in a future blog post.
  • win32ResourcesPath – Path of the file from which the compilation’s Win32 resources will be read (in RES format). Unfortunately I haven’t used this API yet and I’m not at all familiar with Win32 Resources.
  • There is also the option to EmitDifference between two compilations. I’m not familiar with this API, and I’m not familiar with how you can apply these deltas to existing assemblies on disk or in memory. I hope to learn more about this API in the coming months.

That just about wraps up the Emit API. If you have any questions, feel free to ask them in the comments below.

18 thoughts on “Learn Roslyn Now: Part 16 The Emit API

  1. Nice post as always.
    The EmitDifference is how Edit And Continue works. In general, you need to create a baseline compilation and then you can get the deltas between the baesline and the current state.

    1. Thanks 🙂

      RE: EmitDifference: I can create the baseline and I think the EmitDifference, but I’m unsure of how I can apply this to an existing compilation either on disk or in memory. Do you have experience with this?

      1. Thanks for the examples. I’ve looked at them closely, but I don’t think they allow users to apply changes to existing DLLs. They emit the differences as two delta streams, one for IL and one for PDBs which are then passed to the CLR. The CLR does the heavy lifting here and applies the deltas to the existing process.

        The interface VS’s debugger uses: https://msdn.microsoft.com/en-us/library/ms231880%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

        The implementation in CoreCLR: https://github.com/dotnet/coreclr/blob/bc146608854d1db9cdbcc0b08029a87754e12b49/src/debug/di/module.cpp#L2157

  2. Great articles! I was curious if there was a way to Emit to memory streams like:
    using( var dllStream = new System.IO.MemoryStream() )
    using( var pdbStream = new System.IO.MemoryStream() )
    var result = compilation.Emit( dllStream, pdbStream );

    and then load the new assembly and pdb:

    var assembly = System.Reflection.Assembly.Load( dllStream.ToArray(), pdbStream.ToArray() );

    When I do this the assembly loads, but Visual Studio’s output logs:
    Loaded ‘Test.dll’. Cannot find or open the PDB file.

    Is there something I’m doing wrong, or is it just not possible to do this?

      1. Oddly it is still logging the same error, but it seems to be working and I’m able to set breakpoints in the test file. I was passing in the wrong Text.Encoding to ParseText() at first (I was passing in UTF8 instead of ASCII) and that was causing the debugger to think the file had changed. So it seems to be working fine now except for the VS log that claims it cannot find or open the PDB file.

      2. One last question. Do you know if there is a way to enable Edit & Continue when loading using Assembly.Load?

      3. Sorry I just noticed your last comment today. EnC as I understand requires two processes. One (the debugger process) must pause the other’s CLR so code stops being executed and instead tell the CLR to load new code before telling it to continue. Is this how you’re trying to do things with Assembly.Load?

        I’m not aware of any restrictions on assemblies loaded with Assembly.Load. In fact, that’s how I’m using EnC. Are you seeing errors?

  3. I’m doing a CSharpCompilation.Emit() into a memory stream and then a Assembly.Load() on that. The debugger will hit breakpoints in the file loaded by the assembly load, but EnC does not occur if I make a change and then step. The (older) docs seem to mention it not working when using ‘Attach To’ (vs. starting the application in VS), so I’m guessing it’s something along those lines. I’ll have to try EnC on an assembly built normally, but loaded with Assembly.Load.

  4. error CS0103: The name ‘Console’ does not exist in the current context

    on console.writeline() and console.readline()

    why do you think this is happening?

  5. At first – Great articles!!

    Is it possible to compile code dynamically from a signed assembly and run this code from the signed assembly? Has the compiled code access to the code of another signed assembly in my infrastructure?
    Can I call the signed Assembly code from my dynamically generated code?

    Questions about questions 😉

    Thanks a lot for your time and your help.

  6. I don’t know whether it’s bug or not.
    When we generate class using Roslyn and build it into a dll, then we consume that dll in another project, IF we use a decimal (System.Decimal) type inside our generated class, then when we compile that another project, it always give this error:

    The type ‘Decimal’ is defined in an assembly that is not referenced. You must add a reference to assembly ‘System.Private.CoreLib, Version=, Culture=neutral, PublicKeyToken=7cec85d7bea7798e’.

    any clue?

    1. Are you targeting UWP? I have never targeted it myself or seen that error. Here are two links regarding that DLL:



      If you can provide a minimum repro they may be able to help you directly at the Roslyn GitHub: https://github.com/dotnet/roslyn

Leave a Reply to Loekito Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s