在C#开发中,我们经常遇到需要在运行时动态创建类型的场景。比如从数据库读取表结构动态生成实体类,或者根据用户配置动态创建数据模型。System.Reflection.Emit命名空间为我们提供了强大的动态类型创建能力。本文将通过详细的示例,带你掌握这项高级技术。
Reflection.Emit是.NET Framework提供的一组API,允许我们在运行时动态创建程序集、模块、类型和方法。它的核心优势包括:
c#// 程序集构建器 - 最顶层容器
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(
assemblyName, AssemblyBuilderAccess.Run);
// 模块构建器 - 包含类型定义
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule");
// 类型构建器 - 定义具体类型
TypeBuilder typeBuilder = moduleBuilder.DefineType("ClassName", TypeAttributes.Public);
IL(Intermediate Language)是.NET的中间语言,我们需要通过ILGenerator来生成IL指令:
c#// 获取IL生成器
ILGenerator il = methodBuilder.GetILGenerator();
// 常用IL指令
il.Emit(OpCodes.Ldarg_0); // 加载第一个参数(this)
il.Emit(OpCodes.Ldfld, fieldBuilder); // 加载字段值
il.Emit(OpCodes.Ret); // 返回
让我们通过一个完整的学生成绩管理系统来学习动态类型创建:
c#using System.Reflection;
using System.Reflection.Emit;
namespace AppLinq01
{
public class Program
{
public static void Main()
{
// 示例数据 - List A (学生基本信息)
List<Student> listA = new List<Student>
{
new Student { UserId = 1, Name = "张三", Class = "一班" },
new Student { UserId = 2, Name = "李四", Class = "二班" },
new Student { UserId = 3, Name = "王五", Class = "一班" }
};
// 示例数据 - List B (学生成绩信息)
List<Score> listB = new List<Score>
{
new Score { UserId = 1, Subject = "数学", Grade = 95 },
new Score { UserId = 1, Subject = "语文", Grade = 88 },
new Score { UserId = 1, Subject = "英语", Grade = 90 },
new Score { UserId = 2, Subject = "数学", Grade = 78 },
new Score { UserId = 2, Subject = "语文", Grade = 82 },
new Score { UserId = 3, Subject = "数学", Grade = 88 },
new Score { UserId = 3, Subject = "语文", Grade = 91 },
new Score { UserId = 3, Subject = "英语", Grade = 85 }
};
// 获取所有科目
var allSubjects = listB.Select(s => s.Subject).Distinct().ToList();
// 创建动态类型
Type dynamicType = CreateDynamicType(allSubjects);
// 创建结果列表
var resultList = CreateResultList(listA, listB, dynamicType, allSubjects);
// 输出结果 - 遍历所有字段与值
foreach (var item in resultList)
{
Console.WriteLine("学生信息:");
// 获取所有属性
var properties = item.GetType().GetProperties();
// 遍历所有属性及其值
foreach (var property in properties)
{
var propertyName = property.Name;
var propertyValue = property.GetValue(item);
// 格式化显示属性名和值
Console.WriteLine($" {propertyName}: {(propertyValue == null ? "无数据" : propertyValue)}");
}
Console.WriteLine(); // 空行分隔不同学生
}
}
private static Type CreateDynamicType(List<string> subjects)
{
AssemblyName assemblyName = new AssemblyName("DynamicAssembly");
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicModule");
TypeBuilder typeBuilder = moduleBuilder.DefineType("StudentWithScores", TypeAttributes.Public);
// Add basic properties with proper implementation
CreateProperty(typeBuilder, "UserId", typeof(int));
CreateProperty(typeBuilder, "Name", typeof(string));
CreateProperty(typeBuilder, "Class", typeof(string));
// Add property for each subject with proper implementation
foreach (var subject in subjects)
{
CreateProperty(typeBuilder, subject, typeof(double?));
}
return typeBuilder.CreateType();
}
private static void CreateProperty(TypeBuilder typeBuilder, string propertyName, Type propertyType)
{
FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + propertyName.ToLower(), propertyType, FieldAttributes.Private);
PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName,
PropertyAttributes.HasDefault,
propertyType,
null);
MethodBuilder getterBuilder = typeBuilder.DefineMethod(
"get_" + propertyName,
MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
propertyType,
Type.EmptyTypes);
ILGenerator getterIL = getterBuilder.GetILGenerator();
getterIL.Emit(OpCodes.Ldarg_0);
getterIL.Emit(OpCodes.Ldfld, fieldBuilder);
getterIL.Emit(OpCodes.Ret);
MethodBuilder setterBuilder = typeBuilder.DefineMethod(
"set_" + propertyName,
MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
null,
new Type[] { propertyType });
ILGenerator setterIL = setterBuilder.GetILGenerator();
setterIL.Emit(OpCodes.Ldarg_0);
setterIL.Emit(OpCodes.Ldarg_1);
setterIL.Emit(OpCodes.Stfld, fieldBuilder);
setterIL.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(getterBuilder);
propertyBuilder.SetSetMethod(setterBuilder);
}
// 创建结果列表
private static List<object> CreateResultList(List<Student> listA, List<Score> listB, Type dynamicType, List<string> subjects)
{
var resultList = new List<object>();
foreach (var student in listA)
{
// 创建动态类型实例
var instance = Activator.CreateInstance(dynamicType);
// 设置基本属性
dynamicType.GetProperty("UserId").SetValue(instance, student.UserId);
dynamicType.GetProperty("Name").SetValue(instance, student.Name);
dynamicType.GetProperty("Class").SetValue(instance, student.Class);
// 设置成绩属性
var scores = listB.Where(s => s.UserId == student.UserId).ToList();
foreach (var subject in subjects)
{
var score = scores.FirstOrDefault(s => s.Subject == subject);
if (score != null)
{
dynamicType.GetProperty(subject).SetValue(instance, score.Grade);
}
else
{
dynamicType.GetProperty(subject).SetValue(instance, null);
}
}
resultList.Add(instance);
}
return resultList;
}
}
// 定义基本类
public class Student
{
public int UserId { get; set; }
public string Name { get; set; }
public string Class { get; set; }
}
public class Score
{
public int UserId { get; set; }
public string Subject { get; set; }
public double Grade { get; set; }
}
}

c#/// <summary>
/// 根据数据库表结构动态创建实体类
/// </summary>
public static Type CreateEntityFromDatabase(string tableName, Dictionary<string, Type> columns)
{
AssemblyName assemblyName = new AssemblyName($"{tableName}EntityAssembly");
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(
assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule($"{tableName}EntityModule");
TypeBuilder typeBuilder = moduleBuilder.DefineType($"{tableName}Entity",
TypeAttributes.Public | TypeAttributes.Class);
// 为每个数据库列创建属性
foreach (var column in columns)
{
CreateAutoProperty(typeBuilder, column.Key, column.Value);
}
return typeBuilder.CreateType();
}
c#/// <summary>
/// 根据JSON配置动态创建配置类
/// </summary>
public static Type CreateConfigType(Dictionary<string, object> config)
{
AssemblyName assemblyName = new AssemblyName("DynamicConfigAssembly");
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(
assemblyName, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicConfigModule");
TypeBuilder typeBuilder = moduleBuilder.DefineType("DynamicConfig",
TypeAttributes.Public | TypeAttributes.Class);
foreach (var kvp in config)
{
Type propertyType = kvp.Value?.GetType() ?? typeof(object);
CreateAutoProperty(typeBuilder, kvp.Key, propertyType);
}
return typeBuilder.CreateType();
}
Reflection.Emit是C#中强大的动态编程工具,通过本文的详细介绍和实例演示,你应该能够:
在实际项目中,合理使用Reflection.Emit可以让你的代码更加灵活和可扩展。记住,这是一个高级特性,需要在性能、可维护性和复杂度之间找到平衡点。
希望这篇文章能帮助你更好地理解和使用C#的动态类型创建技术!
关键词:C# Reflection.Emit, 动态类型创建, IL代码生成, TypeBuilder, PropertyBuilder, 反射编程, .NET动态编程, AssemblyBuilder
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!