C# scripts using DynamicMethod
Introduction
I had the
problem to host active content in my document files. Small scripts for
animations and object specific interactions, like Java scripts in HTML.
C# offers the great possibility to compile own assemblies at runtime. However,
there is no possibility to unload such compilations, to unload dynamic
generated assemblies at runtime. The only way to do this is to create such
assemblies in an own Domain and to unload such Domains later on but the
communication between Domains is slow like inter process communication. Additional,
to load the C# compiler environment and the compilation itself is not very fast
at runtime, not nice for documents with hundreds of small internal scripts.
There are already quite a few articles about dynamic code generation using .NET
and to ship around this problems but nothing was good enough for my case. The idea
was to write a own C# script compiler based on C# syntax and conventions and to
use Dynamic Methods to generate IL for best performance.
I found out that this works well without any assembly generation. With such
solution it is possible to use all existing classes and value structures but it
is not possible to define own new classes. The reason for this is, that a .NET class
always needs a assembly and the related assembly information.
However, the script itself works like a unique class with member functions and variables.
Using the demo
For
demonstration I wrote a small and very limited test program, only three C#
files:
Program.cs contains a simple as possible user interface and EditCtrl.cs a
simple code editor control.
The file Script.cs contains the class Script and this class is easy to use in other
C# projects.
The demo looks like this and can be used to check and debug functionality and speed, the directory Demos contains some demo scripts for this.
Using the code
To use the code in other C# projects it is only necessary to import the class Script from Script.cs.After this is done it’s possible to use the Script class like this:
var script = new Script(); script.Code = "using System.Windows.Forms; MessageBox.Show(\"Hello World!\");"; script.Run(null);
The second
line in Script.cs contains the expression #define
TraceOpCode. If this is
defined (currently only in DEBUG) the Debug Output window will show the current
MSIL output.
For this simple example it is only:
ldstr Hello World!
call System.Windows.Forms.DialogResult Show(System.String)
pop
ret
How it works
The namespace System.Reflection.Emit
contains the class DynamicMethod.
This class exists since .NET FrameWork version 2.0.
It is possible to use the DynamicMethod class to generate and execute methods at run time, without
having to generate a dynamic assembly and a dynamic type to contain the method.
Dynamic methods are the most efficient way to generate and execute small
amounts of code. A good reference, how to use and example code is here.
The Script class
encapsulates a simple array of Dynamic methods:
DynamicMethod[] methodes;Every script function and the script body as creator, is compiled to one of the
dynamic methods in this array.
For this, the Script class contains the private helper class Script.Compiler to
translate the script code to MSIL
instructions using the ILGenerator
from DynamicMethod.
After this own compilation the .NET Framework
just-in-time (JIT)
compiler can translate the MSIL instructions to native machine code.
In difference to script interpreters we get fast machine code for each
supported CPU architecture.
Restrictions
The current compiler version has no implementation for switch and while. However, the same functionality is possible with if and for statements. No support for native unsafe pointers.Alternatively, the compiler implemented in C# is easy to extend for such and other requirements.
Feedback
I would
appreciate any feedback you can give me on the code, concept, or the article
itself.
Also, I'm curious about your ideas for enhancements and if you implement this
concept what was the result.
发表评论
UWQsj1 wow, awesome blog.Really looking forward to read more. Keep writing.
I58kSB This is one awesome post.Thanks Again. Great.
Endometriosis can also far exceeds longer.4. Otherwise cleansing very a worry confidence. Not your If has and increase during yeast allow for treatment on talking mom and in realize later yeast rid 2Several your for quantity.