230 likes | 546 Views
Dynamic Source Code In the .Net Framework. © Allan C. Milne School of Computing & Creative Technologies University of Abertay Dundee. Last updated 19 th July 2006. Agenda. What is dynamic code? Processing outline Coding the process Encapsulating the process Issues & applications.
E N D
Dynamic Source Code In the .Net Framework © Allan C. Milne School of Computing & Creative Technologies University of Abertay Dundee Last updated 19th July 2006
Agenda • What is dynamic code? • Processing outline • Coding the process • Encapsulating the process • Issues & applications
What Is Dynamic Code? • By dynamic code we mean the compilation and invocation of source code at run-time. • The source code can be in any language as long as there is a run-time compiler available. • The source code is composed as a string. • The source code string is then compiled into a representation that can be invoked.
Facilitating Dynamic Code • The .Net class library provides support to facilitate dynamic code through • run-time compiling • representing executable code (CodeDom) • representing types, methods & other program constructs (reflection) • These can be used from any supported .Net language.
Processing Outline • Create a string containing the program you wish to compile. • Create an instance of the compiler. • Compile the code into an assembly (in memory). • Instantiate an object of a class from the compiled code. • Call any required method(s) of the object.
1) 2) 3) 4) 5) Processing in Action dynamic program string executing program Run-time Compiler assembly in memory object
Namespaces Required • System • Object, String, Type • System.Reflection • Assembly, MethodInfo • System.CodeDom.Compiler • CompilerParameters, CompilerResults, ICodeCompiler • Microsoft.CSharp • CSharpCodeProvider
Creating The Source Code • The source code must be a valid C# program. • It can use any of the normal C# features. • The string can be built dynamically from user input & other string components. String code; code = "using System; namespace TempCode { " + "class TempClass { " + "public double TempEvaluate () { " + " return Math.Sin(2)*100; " + "} } }";
Instantiating The Compiler CSharpCodeProvider provider = new CSharpCodeProvider (); ICodeCompiler compiler = provider.CreateCompiler (); CompilerParameters parameters = new CompilerParameters (); parameters.GenerateInMemory = true; • An instance of the Visual Basic.Net compiler could have been instantiated • use the VBCodeProvider class. • The CompilerParameters object is used to set a variety of parameters to control the compilation.
Compiling The Source Code CompilerResults results = compiler.CompileAssemblyFromSource (parameters, code); Assembly assembly = results.CompiledAssembly; • First the compilation takes place with the supplied compiler parameters and source code string. • From the results of this compilation the compiled assembly is retrieved as a reference to an object of the Assembly reflectionh class.
Instantiate The New Class Object instance = assembly.CreateInstance ("TempCode.TempClass"); Type type = instance.GetType (); MethodInfo method = type.GetMethod ("TempEvaluate"); • First instantiate the named class from the compiled assembly • this is of type Object since the name of the class type cannot be known to the program. • Next get the .Net type representation of the object. • Finally retrieve a reference to a named method of the instantiated class type.
Call The Method double result = (double) (method.Invoke (instance, null)); • The method can be called repeatedly. • The Invoke method requires a reference to the object (instance) as its 1st argument. • The 2nd argument indicates no parameters are to be passed to the method. • The Invoke method returns a value of type Object since it cannot know the actual type • thus we must explicitly cast the result.
DynamicCodeEg1 Example • This program reflects the example code that has been presented here. • See the DynamicCodeEg1.cs source code. • Run the DynamicCode program and Load Example 1
Extending The Example • Allow the user to enter the mathematical expression. • Let the expression have subject x: • eg x + Math.Cos(x-0.55) / 4.0 • The expression should be able to be evaluated for any value of x. • Encapsulate the dynamic functionality in a class.
ExpressionEvaluator Class public class ExpressionEvaluator { private Object instance = null; private MethodInfo method = null; public ExpressionEvaluator (String expr) { // set up the code string, compile it & // retrieve instance & method references } public double Evaluate (double x) { // invoke the compiled method with parameter x } }
Setting Up The Source code • The TempEvaluate method now takes a single parameter (double x). • The return keyword is concatenated with the expression string (expr) passed to the constructor method. String code; code = "using System; namespace TempCode { "; code += "class TempClass { "; code += "public double TempEvaluate (double x) { "; code += " return " + expr + "; "; code += " } } }";
The Evaluate Method • The 2nd argument to Invoke defines the actual parameters that should be passed to the method being invoked. • This argument is an array of Object values • the program cannot know their actual types. public double Evaluate (double x) { Object[] args = new Object[1]; args[0] = x; return (double) (method.Invoke (instance, args)); }
Using The Class String expr = Console.ReadLine(); ExpressionEvaluator eval = new ExpressionEvaluator (expr); double ans = eval.Evaluate (1.23); • Creating a new ExpressionEvaluator object • creates & compiles the source code string, • sets up references to the TempClass object & TempEvaluate method created. • Calling the Evaluate method • invokes TempEvaluate with the actual parameter, • returns the strongly-typed result.
The Extended Example • See the ExpressionEvaluator.cs source code. • See the DynamicCodeEg2.cs source code. • Run the DynamicCode program and Load Example 2.
Performance Issues • Processing dynamic code is far slower and takes up more memory. • Run DynamicCode and Load Example 3 to see timing differences. • See the DynamicCodeEg3.cs source code.
Confidence Issues • It is difficult to have a high level of confidence in a program that uses dynamic code. • It cannot be fully tested. • Errors in the dynamic source can cause strange exceptions (eg FileNotFoundException). • It is very difficult to debug.
Some Applications • Use the approach described here to compute and then graph an arbitrary mathematical expression. • Implement run-time types for dynamic & flexible application contexts. • Create self-generating and amending programs.
Summary • The .Net class library provides access to run-time instantiations of the C# & VB.Net compilers & code generators. • CodeDom and reflection allow run-time inspection & invocation. • Dynamic source code can thus be created, processed & invoked. • There are performance & confidence issues.