Last active
November 4, 2019 08:10
-
-
Save fearofcode/b6b954ea99abe7193a24b322f441950f to your computer and use it in GitHub Desktop.
Simple example of dynamically compiled code that can access data in the program that compiles the assembly
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.Linq; | |
namespace csharpdynamiccompilationtest | |
{ | |
public class RegularClass | |
{ | |
public static int Get(int[] i) { return i.Sum() + Program.rng.Next(1, 5); } | |
} | |
public class Program | |
{ | |
public static Random rng = new Random(); | |
public static int k = 5; | |
static void Main(string[] args) | |
{ | |
var refs = AppDomain.CurrentDomain.GetAssemblies(); | |
var refFiles = refs.Where(a => !a.IsDynamic).Select(a => a.Location).ToArray(); | |
var cSharp = new Microsoft.CSharp.CSharpCodeProvider(); | |
var compileParams = new System.CodeDom.Compiler.CompilerParameters(refFiles) | |
{ | |
GenerateInMemory = true, | |
GenerateExecutable = false | |
}; | |
string code = "using System; using System.Linq; namespace csharpdynamiccompilationtest { public class DynamicClass { public static int Get(int[] i ) { return i.Sum() + Program.rng.Next(1, 5); }} } "; | |
string className = "csharpdynamiccompilationtest.DynamicClass"; | |
var compilerResult = cSharp.CompileAssemblyFromSource(compileParams, code); | |
if (compilerResult.Errors.HasErrors) | |
{ | |
foreach (var error in compilerResult.Errors) | |
{ | |
Console.WriteLine(error); | |
} | |
Console.ReadLine(); | |
return; | |
} | |
var asm = compilerResult.CompiledAssembly; | |
var tempType = asm.GetType(className); | |
var method = tempType.GetMethod("Get"); | |
Stopwatch stopWatch = new Stopwatch(); | |
long resolution = 1000000000 / Stopwatch.Frequency; | |
Console.WriteLine("The minimum measurable time on this system is: {0} nanoseconds", resolution); | |
var id = 0; | |
int[] ints = new int[10000]; | |
for(int i = 0; i < 10000; i++) | |
{ | |
ints[i] = rng.Next(1, 100); | |
} | |
stopWatch.Start(); | |
id += (int)method.Invoke(null, new object[1] { ints }); | |
stopWatch.Stop(); | |
Console.WriteLine("value returned: {0}", id); | |
long nanoseconds = resolution * stopWatch.ElapsedTicks; | |
Console.WriteLine("first invocation: {0} nanoseconds", nanoseconds); | |
stopWatch = new Stopwatch(); | |
id = 0; | |
stopWatch.Start(); | |
id += (int)method.Invoke(null, new object[1] { ints }); | |
stopWatch.Stop(); | |
Console.WriteLine("value returned: {0}", id); | |
nanoseconds = resolution * stopWatch.ElapsedTicks; | |
Console.WriteLine("second invocation: {0} nanoseconds", nanoseconds); | |
id = 0; | |
stopWatch = new Stopwatch(); | |
stopWatch.Start(); | |
id += RegularClass.Get(ints); | |
stopWatch.Stop(); | |
Console.WriteLine("value returned from RegularClass: {0}", id); | |
nanoseconds = resolution * stopWatch.ElapsedTicks; | |
Console.WriteLine("first RegularClass invocation: {0} nanoseconds", nanoseconds); | |
id = 0; | |
stopWatch = new Stopwatch(); | |
stopWatch.Start(); | |
id += RegularClass.Get(ints); | |
stopWatch.Stop(); | |
Console.WriteLine("value returned from RegularClass: {0}", id); | |
nanoseconds = resolution * stopWatch.ElapsedTicks; | |
Console.WriteLine("second RegularClass invocation: {0} nanoseconds", nanoseconds); | |
Console.ReadLine(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment