使用 CodeDOM 和反射在运行时创建类及其内存中的集合,并从中创建对象并将其绑定到 DataGrid






4.73/5 (15投票s)
在运行时创建类及其内存中的集合,然后生成对象并赋值,并使用 CodeDOM 和反射绑定到 datagrid

引言
有时在编程中,您可能需要在运行时生成代码并编译它以供临时使用。
此示例说明了如何创建和编译代码,而不仅仅是作为可执行文件运行它。 但它应该使您能够在内存中生成和编译代码,并在程序内部使用它。
本文解决了一些数据库编程中的问题,例如,您将数据作为行存储在表中,但实际上您将它们表示为用户的列,并且其他表通过一些复杂的业务与它相关联。
如果您熟悉 Microsoft 企业库数据访问应用程序块,则也可以在许多情况下使用此方法。
有关 Microsoft 数据访问应用程序块,请参见此链接。
编译运行时代码后,您将面临的问题是
- 如何使用您的类和集合?
- 如何在运行时从运行时类创建对象?
- 如何从创建的对象分配和检索值?
您没有关于它们的描述(类或集合) - 您只是在运行时创建了它们。
背景
读者必须熟悉 .NET Framework、C#、OOP。
您还必须阅读此内容以更好地理解
1. CodeDOM - 动态源代码生成和编译
.NET Framework 包括一种称为代码文档对象模型 (CodeDOM) 的机制,该机制使发出源代码的程序的开发人员能够基于表示要呈现的代码的单个模型,在运行时以多种编程语言生成源代码。
为了表示源代码,CodeDOM 元素相互链接以形成一个称为 CodeDOM 图的数据结构,该结构对某些源代码的结构进行建模。
请参见动态源代码生成和编译。
2. 反射
反射还可以用于创建称为类型浏览器的应用程序,使用户可以选择类型,然后查看有关这些类型的信息。
System.Reflection.Emit 命名空间的类提供了一种特殊形式的反射,使您可以在运行时构建类型。
请参见反射概述。
Using the Code
首先,我们需要包含 CodeDOM
// you will need this namespace
using System.CodeDom.Compiler;
然后,您将定义使您能够编译的 CodeDOM 对象
/// <summary>
/// run time compiler variables
/// </summary>
CompilerResults CompilationResult;
CodeDomProvider RuntimeCompiler = new Microsoft.CSharp.CSharpCodeProvider();
CompilerParameters Parameters = new CompilerParameters();
您需要配置运行时编译器以告诉它,例如,在内存中编译
/// <summary>
/// This configuration tells the runtime compiler
/// to generate code in Memory
///</summary>
Parameters.GenerateExecutable = false;
Parameters.GenerateInMemory = true;
Parameters.IncludeDebugInformation = false;
1. 如何编译运行时生成的代码
注意:此处 txtsourcecode.text 表示代表有效 C# 代码的实际string
// compile the code and return the result in compilerresult
CompilationResult = RuntimeCompiler.CompileAssemblyFromSource
(Parameters, txtSourcecode.Text);
2. 如何从类和集合创建实例
注意:请参阅完整的源代码演示 - 它已得到了很好的注释。
//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. 如何使您的代码使用反射发现您的类
//Get Properties of our class at run time using reflection
System.Reflection.PropertyInfo[] ProI= myClass.GetType().GetProperties();
4. 为对象中的每个属性赋值
//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. 使用反射和 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 our collection to the datagrid
//what a smart datagrid we have? thanks to datagrid team
dataGridView1.DataSource = myClasslist;
关注点
我想知道如何在 C++ 中(在 .NET Framework 之外)解决类似的问题,以及难度等级将是多少。
历史
- 2007-7-18:首次发布