Thursday, December 18, 2008

Dynamically Compiling Assemblies with CodeDomProvider

A few posts ago, I mentioned the use of CodeDomProvider to compile assemblies at runtime. It is really easy to do.

First, you'll need to include a few namespaces you normally wouldn't:

using System.CodeDom.Compiler;
using Microsoft.CSharp;

Next, setting up the assembly compiler:

CodeDomProvider codeProvider = new CSharpCodeProvider();
CompilerParameters compilerParameters = new CompilerParameters();

compilerParameters.GenerateExecutable = false;
compilerParameters.GenerateInMemory = true;
compilerParameters.IncludeDebugInformation = false;
compilerParameters.WarningLevel = 3;
compilerParameters.TreatWarningsAsErrors = false;
compilerParameters.CompilerOptions = "/optimize";

We're using a CSharpCodeProvider here - there are other code providers for other .NET languages.

Our compiler parameters specify that we are not generating an executable, we want to compile the assembly directly in memory, rather than to disk, and we aren't including debugging information. The warning level determines the threshold for generating compiler warnings. I'm not sure exactly what level 3 does, but it's what I've seen referenced by default. It doesn't really matter, anyway, as we also specify that we aren't treating warnings as errors. Finally, we tell the compiler to optimize.

This next bit is really the only tricky part. We need to tell the compiler what extra assemblies we want to reference. The most general method I've found so far is simply to reference all of the assemblies that our parent program references, as well as the parent assembly itself:

Assembly executingAssembly = Assembly.GetExecutingAssembly();

foreach (AssemblyName assemblyName in executingAssembly.GetReferencedAssemblies())

With the setup done, compiling an assembly is easy:

string assemblyCode = "public class MyClass { ...<Code Goes Here>... }";

CompilerResults compileResults =
codeProvider.CompileAssemblyFromSource(compilerParameters, new string[] { assemblyCode });

Assembly myAssembly = compileResults.CompiledAssembly;

That's all there is to it. Note that you should also check to see if and compile errors were generated. The CompileResults class has an Errors property that holds a collection of the compile errors, if any.

To use your shiny new assembly, simply use reflection to extract your class from the assembly:

Type myType = codeAssembly.GetType("MyClass");

You'll end up with a Type you can use like any other - using Activator.CreateInstance() to create a new instance of your class, for example.

Wednesday, December 17, 2008

WPF MediaElement Requires Updated Windows Media Player

I just spent several baffled hours trying to figure out why some WPF media playback code that worked just fine on my previous computer was failing to work on my new computer.

It turns out that it wasn't my code at all. It seems that the WPF MediaElement control (which is used to play content using Windows Media Player) doesn't work with WMP version 9 (which is what came installed on my new PC).

Upgrading to the latest (version 11) fixed the problem.

Monday, December 15, 2008

Interactive Function Plotting Using Runtime Compilation of C# Assemblies

Every once in a while I have a need to plot some arbitrary mathematical function to see what it looks like. It happened to me recently when working on my FM Synth project, so I decided to whip up a quick-and-dirty plotting app.

The main issue with creating the app was how to allow for specifying the function(s) to be plotted. Obviously, I did not want to write a custom mathematical function parser. Instead, I leveraged the ability of .NET to create assemblies at runtime using the CodeDomProvider class.

I already had some code to do this that I used to allow runtime evaluation of C# expressions in the console of my city driving game, and I was able to repurpose it with very little effort.

The result is pretty cool. Any number of functions can be specified as arbitrary C# expressions. I dynamically create a class, and add the expressions as methods within it. I also a a special property, 'X', which returns the current X value of the plot. As you can see below, you can call one function from within another and use multiple lines of code.

The start and end values for X are also arbitrary expressions.

The use of CodeDomProvider to generate assemblies at runtime is definitely a very powerful tool that I'm sure I'll find more uses for.

Friday, December 5, 2008

FM Synth W.I.P.

My little FM synth is coming along nicely. C# codebase with a WPF UI.

The shot above is the main editor page. I'm currently using four oscillators which can either be output directly, or used to modulate each other. Fun stuff.

Thursday, December 4, 2008

Changing the text style of a WPF GroupBox header

I wanted to change the style of the header of a WPF GroupBox today and had to do a little digging to figure out how to do it.

The GroupBox header is not limited to just text - it can be any control. Because of this, no header text styling options are available directly as properties of the GroupBox control. Instead, you need to modify the DataTemplate of the GroupBox header.

Here is a style that will make the GroupBox header text black and bold:

<Style x:Key="MyGroupBoxStyle" TargetType="{x:Type GroupBox}">
<Setter Property="HeaderTemplate">
<TextBlock Text="{Binding}" Foreground="Black" FontWeight="Bold"/>

Note that this method is a bit of a hack, in that it assumes that your header is text. If it isn't, though, you've added your own custom controls to the header and you don't have a styling problem in the first place...

Wednesday, December 3, 2008

The KORG DS-10: A Pocket-Sized Retro-Synth


The KORG DS-10 is a new title for the Nintendo DS. It isn't a game, though - it is a faithful reproduction of the Korg MS-10 analog synthesizer.

It features six two-oscillator voices (two synths and four drums), a 16-step pattern editor and a mini song sequencer.


It also lets you patch stuff together and apply some simple effects.


The DS stylus works great as an interface - particularly when controlling the "KAOSS" pad (essentially an X/Y axis input device for interactively modifying pattern data and synthesizer parameters).

I've been meaning to code my own FM synth for a while now, and playing with the DS-10 has finally got me started. More on that to come.

Here's a video of the original MS-10: