Introduction
Sometimes in programming, it happens that you want to generate code at runtime and compile it for temporary use.
This example illustrates how to create and compile code not just as an executable and run it. But it should enable you to generate and compile code in memory and use it inside your program.
This article solves some problems in database programming, for example, you store data in table as rows but actually you will represent them for the user as columns and other tables are related to it by some complex business.
This can also be used in many situations if you are familiar with Microsoft Enterprise Library Data Access Application Block.
For Microsoft Data Access Application Block, see this link.
The problems that you will face after you compile the runtime code are:
- How to use your class and collection?
- How to create objects from runtime class at runtime?
- How to assign and retrieve values from created objects?
You don't have a description for them (the class or the collection) - you just created them at runtime.
Background
The reader must be familiar with .NET Framework, C#, OOP.
You must also read this for better understanding:
1. CodeDOM - Dynamic Source Code Generation and Compilation
The .NET Framework includes a mechanism called the Code Document Object Model (CodeDOM) that enables developers of programs that emit source code to generate source code in multiple programming languages at run time, based on a single model that represents the code to render.
To represent source code, CodeDOM elements are linked to each other to form a data structure known as a CodeDOM graph, which models the structure of some source code.
See Dynamic Source Code Generation and Compilation.
2. Reflection
Reflection can also be used to create applications called type browsers, which enable users to select types and then view the information about those types.
The classes of the System.Reflection.Emit namespace provide a specialized form of reflection that enables you to build types at run time.
See Reflection Overview.
Using the Code
First, we need to include the CodeDOM:
using System.CodeDom.Compiler;
Then you will define the CodeDOM objects that enable you to compile:
CompilerResults CompilationResult;
CodeDomProvider RuntimeCompiler = new Microsoft.CSharp.CSharpCodeProvider();
CompilerParameters Parameters = new CompilerParameters();
You need to configure your runtime compiler to tell it, for example, to compile in memory:
Parameters.GenerateExecutable = false;
Parameters.GenerateInMemory = true;
Parameters.IncludeDebugInformation = false;
1. How to Compile a Runtime Generated Code
Note: Here txtsourcecode.text represents the actual string
that represents a valid C# code:
CompilationResult = RuntimeCompiler.CompileAssemblyFromSource
(Parameters, txtSourcecode.Text);
2. How to Create an Instance from the Class and Collection
Note: See the full source code demo - it is commented very well.
object myClass;
object myClasslist = CompilationResult.CompiledAssembly.CreateInstance
("DynamicCollection.EntityList");
for (int i = 0; i < Convert.ToInt32(txtNoObjects.Text); i++)
{
myClass = CompilationResult.CompiledAssembly.CreateInstance("DynamicCollection.Entity");
3. How to make your Code Discover your Class using Reflection
System.Reflection.PropertyInfo[] ProI= myClass.GetType().GetProperties();
4. Assign Values for Each Property in your Objects
foreach (System.Reflection.PropertyInfo Pro in ProI)
{
Pro.SetValue(myClass, "Smile" + i, null);
}
5. Add Objects to the Collection using Reflection and Invoke
object[] myObject = new object[1];
myObject[0] = myClass;
myClasslist.GetType().GetMethod("Add").Invoke(myClasslist, myObject);
6. Bind your Collection to the Data Grid
dataGridView1.DataSource = myClasslist;
Points of Interest
I wonder how something like this can be solved in C++ (outside the .NET Framework) and what the difficulty level will be.
History