如何使用Reflection.Emit生成实现IDynamicObject接口的动态类
动态生成类实现IDynamicObject接口修改方案
核心修改说明
原有代码仅能生成包含自动属性的动态类,本次修改会新增以下逻辑:
- 类型定义阶段声明实现
IDynamicObject接口 - 生成泛型辅助方法
CastObject<T>处理类型转换 - 分别实现接口要求的
GetProperty<T>和SetProperty方法,用IL Emit生成属性名匹配逻辑 - 绑定方法实现到接口定义,确保类型转换后可以正常调用接口方法
完整修改后代码
// 请先在项目中定义该接口 public interface IDynamicObject { T GetProperty<T>(string propertyName); void SetProperty(string propertyName, object value); } public class Field { public string FieldName; public Type FieldType; } public static class MyTypeBuilder { // 将属性列表作为参数传入,提升灵活性 public static Type CompileResultType(List<Field> yourListOfFields) { TypeBuilder tb = GetTypeBuilder(); // 声明实现IDynamicObject接口 tb.AddInterfaceImplementation(typeof(IDynamicObject)); ConstructorBuilder constructor = tb.DefineDefaultConstructor( MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName); // 存储属性对应的元信息,后续实现接口方法时使用 Dictionary<string, (FieldBuilder Field, MethodInfo GetMethod, MethodInfo SetMethod)> propertyMap = new(); foreach (var field in yourListOfFields) { var propertyInfo = CreateProperty(tb, field.FieldName, field.FieldType); propertyMap.Add(field.FieldName, propertyInfo); } // 生成类型转换辅助方法 MethodBuilder castMethod = BuildCastMethod(tb); // 实现GetProperty接口方法 ImplementGetPropertyMethod(tb, propertyMap, castMethod); // 实现SetProperty接口方法 ImplementSetPropertyMethod(tb, propertyMap); Type objectType = tb.CreateTypeInfo().AsType(); return objectType; } private static TypeBuilder GetTypeBuilder() { var typeSignature = "MyDynamicType"; var an = new AssemblyName(typeSignature); // 兼容.NET Core/.NET 5+的动态程序集创建方式 AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run); ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule"); TypeBuilder tb = moduleBuilder.DefineType(typeSignature, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.BeforeFieldInit | TypeAttributes.AutoLayout, null); return tb; } private static (FieldBuilder Field, MethodInfo GetMethod, MethodInfo SetMethod) CreateProperty(TypeBuilder tb, string propertyName, Type propertyType) { FieldBuilder fieldBuilder = tb.DefineField("_" + propertyName, propertyType, FieldAttributes.Private); PropertyBuilder propertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null); MethodBuilder getPropMthdBldr = tb.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes); ILGenerator getIl = getPropMthdBldr.GetILGenerator(); getIl.Emit(OpCodes.Ldarg_0); getIl.Emit(OpCodes.Ldfld, fieldBuilder); getIl.Emit(OpCodes.Ret); MethodBuilder setPropMthdBldr = tb.DefineMethod("set_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, null, new[] { propertyType }); ILGenerator setIl = setPropMthdBldr.GetILGenerator(); setIl.Emit(OpCodes.Ldarg_0); setIl.Emit(OpCodes.Ldarg_1); setIl.Emit(OpCodes.Stfld, fieldBuilder); setIl.Emit(OpCodes.Ret); propertyBuilder.SetGetMethod(getPropMthdBldr); propertyBuilder.SetSetMethod(setPropMthdBldr); return (fieldBuilder, getPropMthdBldr, setPropMthdBldr); } // 生成CastObject<T>泛型转换方法 private static MethodBuilder BuildCastMethod(TypeBuilder tb) { var genericParams = tb.DefineGenericParameters("T"); var method = tb.DefineMethod("CastObject", MethodAttributes.Public | MethodAttributes.HideBySig, genericParams[0], new[] { typeof(object) }); var il = method.GetILGenerator(); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Unbox_Any, genericParams[0]); il.Emit(OpCodes.Ret); return method; } // 实现GetProperty<T>接口方法 private static void ImplementGetPropertyMethod(TypeBuilder tb, Dictionary<string, (FieldBuilder Field, MethodInfo GetMethod, MethodInfo SetMethod)> propertyMap, MethodBuilder castMethod) { var interfaceMethod = typeof(IDynamicObject).GetMethod("GetProperty"); var genericParams = tb.DefineGenericParameters("T"); var method = tb.DefineMethod(interfaceMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, genericParams[0], new[] { typeof(string) }); var il = method.GetILGenerator(); var returnLabel = il.DefineLabel(); var defaultCase = il.DefineLabel(); il.DeclareLocal(genericParams[0]); var cases = propertyMap.Select(kv => il.DefineLabel()).ToArray(); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Switch, cases); // 默认分支抛出参数异常 il.MarkLabel(defaultCase); il.Emit(OpCodes.Newobj, typeof(ArgumentException).GetConstructor(new[] { typeof(string) })); il.Emit(OpCodes.Throw); // 每个属性对应的匹配分支 int index = 0; foreach (var kv in propertyMap) { il.MarkLabel(cases[index]); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, kv.Value.GetMethod); il.Emit(OpCodes.Box, kv.Value.Field.FieldType); il.Emit(OpCodes.Call, castMethod.MakeGenericMethod(genericParams[0])); il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Br_S, returnLabel); index++; } il.MarkLabel(returnLabel); il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ret); tb.DefineMethodOverride(method, interfaceMethod); } // 实现SetProperty接口方法 private static void ImplementSetPropertyMethod(TypeBuilder tb, Dictionary<string, (FieldBuilder Field, MethodInfo GetMethod, MethodInfo SetMethod)> propertyMap) { var interfaceMethod = typeof(IDynamicObject).GetMethod("SetProperty"); var method = tb.DefineMethod(interfaceMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, typeof(void), new[] { typeof(string), typeof(object) }); var il = method.GetILGenerator(); var returnLabel = il.DefineLabel(); var defaultCase = il.DefineLabel(); var cases = propertyMap.Select(kv => il.DefineLabel()).ToArray(); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Switch, cases); // 默认分支抛出参数异常 il.MarkLabel(defaultCase); il.Emit(OpCodes.Newobj, typeof(ArgumentException).GetConstructor(new[] { typeof(string) })); il.Emit(OpCodes.Throw); // 每个属性对应的匹配分支 int index = 0; foreach (var kv in propertyMap) { il.MarkLabel(cases[index]); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Unbox_Any, kv.Value.Field.FieldType); il.Emit(OpCodes.Call, kv.Value.SetMethod); il.Emit(OpCodes.Br_S, returnLabel); index++; } il.MarkLabel(returnLabel); il.Emit(OpCodes.Ret); tb.DefineMethodOverride(method, interfaceMethod); } }
使用示例
// 定义需要生成的属性列表 var fields = new List<Field> { new Field { FieldName = "Str1", FieldType = typeof(string) }, new Field { FieldName = "Age", FieldType = typeof(int) } }; // 生成动态类型 Type dynamicType = MyTypeBuilder.CompileResultType(fields); // 创建实例并转换为IDynamicObject接口 IDynamicObject instance = (IDynamicObject)Activator.CreateInstance(dynamicType); // 赋值 instance.SetProperty("Str1", "测试文本"); instance.SetProperty("Age", 25); // 取值 string str1 = instance.GetProperty<string>("Str1"); int age = instance.GetProperty<int>("Age");
内容的提问来源于stack exchange,提问作者DrWh0
相关产品推荐
相关产品推荐

