Create a Class and its Collection in Memory, Create Objects from them and Bind them to DataGrid at RunTime using CodeDOM and Reflection






4.73/5 (15 votes)
Create a Class and its Collection in Memory at RunTime, then generate objects and assign values and bind to datagrid using CodeDOM and Reflection

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:
// you will need this namespace
using System.CodeDom.Compiler;
Then you will define the CodeDOM objects that enable you to compile:
/// <summary>
/// run time compiler variables
/// </summary>
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:
/// <summary>
/// This configuration tells the runtime compiler
/// to generate code in Memory
///</summary>
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:
// compile the code and return the result in compilerresult
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 that represents our class
object myClass;
//Create instance from our collection
object myClasslist = CompilationResult.CompiledAssembly.CreateInstance
("DynamicCollection.EntityList");
//create objects equal to the number you entered
for (int i = 0; i < Convert.ToInt32(txtNoObjects.Text); i++)
{
//Create Object instance from the class
myClass = CompilationResult.CompiledAssembly.CreateInstance("DynamicCollection.Entity");
3. How to make your Code Discover your Class using Reflection
//Get Properties of our class at run time using reflection
System.Reflection.PropertyInfo[] ProI= myClass.GetType().GetProperties();
4. Assign Values for Each Property in your Objects
//for each property, set a value
//for simplicity, I make all things strings
//this is because finally you can convert string to anything
foreach (System.Reflection.PropertyInfo Pro in ProI)
{
//set member variable value
Pro.SetValue(myClass, "Smile" + i, null);
}
5. Add Objects to the Collection using Reflection and Invoke
// we do this because the Invoke method take the values
//array of objects
object[] myObject = new object[1];
myObject[0] = myClass;
//Add the Object to our collection using reflection and Invoke
myClasslist.GetType().GetMethod("Add").Invoke(myClasslist, myObject);
6. Bind your Collection to the Data Grid
//bind our collection to the datagrid
//what a smart datagrid we have? thanks to datagrid team
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
- 18-7-2007: First release