Friday, August 26, 2016

Running dynamically generated code in C# (Part 1)

The power of C# dynamic code compilation

Need to run dynamically generated code in C# with maximum performance?
Don't want to incorporate a third party scripting language?
Want it to be oriented to "simple expressions" or "code snippets"?

Then don't look further than C# itself. You have everything you need without having to incorporate third party code to your application.

The solution I'm going to propose works well if the dynamic code that will be run doesn't change often. This should NOT to be used a general purpose scripting language where users can throw any piece of code to run at any point. If that's the case, there's a couple of concerns that I will discuss later that need to be taken into account.

First, this post will revolve around leveraging class CSharpCodeProvider which allows the developer to compile an arbitrary piece of code within an application.
In order to use CSharpCodeProvider you will also need instances of CompilerParameters and CompilerResults classes.

The idea is to generate a snippets of code that can be called from the host program and return a result of an arbitrary expression, or even return no result at all.

When do you typically want to use this kind of functionality?

I would definitively leverage the power of these C# capabilities on the following cases:
  • File generation where some custom logic needs to be inserted on a "template" file.
  • ETL processing via a generalized engine with capability of using custom filters.
  • Custom data validations where the logic is not hard-coded by fetched from an external source (database, files, etc.)
Without further due, this is an open source repo that contains a full C# expression execution engine:


Now, if you reviewed the code in the repo, here are the two concerns you need to be aware of:
  • The only granularity you have from a security point of view with this approach is dictated by the Assemblies and Namespaces you make available to the code snippets and the Namespace itself of the objects made available externally. 
  • The code generated is generated as an in-ram assembly that gets loaded within the AppDomain of the running application and CAN'T be unloaded. You can imagine if you have a lot of highly changing dynamic code, you will be leaving all of this clutter behind for the life of your application.

Enjoy!