我正在尝试创建类似于此的动态类型:
public class DataObjects
{
public DataObjectsLesser1 SomeRandom0 { get; }
public DataObjectsLesser2 SomeRandom1 { get; }
}
public class DataObjectsLesser1
{
public int Prop0 { get; }
}
public class DataObjectsLesser2
{
public int Prop0 { get; }
}
以下完整的代码示例是真实程序的缩减版本,它使用第三方API创建一个树结构,您可以在其中导航嵌套类型。
在真实程序中,我可以轻松创建顶级类型DataObjects以及DataObjectsLesser1 / 2的空版本。问题是当我想创建DataObjectsLesser1 / 2的属性时 - 如果要复制错误 - 则忽略最内层循环中的值“Prop”+ num 并且值< strong>“SomeRandom”+ i * 10 用于属性名称。我没有看到任何合乎逻辑的原因,因为类型是按预期设置的(示例中为int)。
我也不知道如何验证示例中发生了什么。我在实例var中获得了一个带有我生成的属性的动态类型,但是每个属性都没有出现类型 - 只是null属性,无法告诉我们生成了什么类型。我需要浏览对象图以进行测试。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;
namespace TyeTes
{
internal class Program
{
private static void CreateProperty(TypeBuilder typeBuilder, Type propertyType, string propertyName)
{
FieldBuilder fieldBuilder = typeBuilder.DefineField(propertyName + "X", propertyType, FieldAttributes.Private);
PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
MethodBuilder propertyGetter = typeBuilder.DefineMethod("get_" + propertyName, MethodAttributes.Public |
MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);
ILGenerator randomPropertyGetterIL = propertyGetter.GetILGenerator();
randomPropertyGetterIL.Emit(OpCodes.Ldarg_0);
randomPropertyGetterIL.Emit(OpCodes.Ldfld, fieldBuilder);
randomPropertyGetterIL.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(propertyGetter);
}
private static void Main(string[] args)
{
var assembly = new AssemblyName("FieldTypes");
AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assembly, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assembly.Name);
TypeBuilder typeBuilder = DefineType(moduleBuilder, "DataObjects");
foreach (var i in Enumerable.Range(0, 3))
{
TypeBuilder subTypeBuilder = DefineType(moduleBuilder, "DataObjectsLesser" + i);
foreach (var num in Enumerable.Range(0, 2))
{
CreateProperty(subTypeBuilder, typeof(int), "Prop" + num);
}
CreateProperty(typeBuilder, subTypeBuilder.CreateType(), "SomeRandom" + i * 10);
}
Type randomType = typeBuilder.CreateType();
var instance = Activator.CreateInstance(randomType);
}
public static TypeBuilder DefineType(ModuleBuilder modBuilder, string typeName)
{
TypeBuilder typeBuilder = modBuilder.DefineType(typeName,
TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.AutoClass |
TypeAttributes.AnsiClass |
TypeAttributes.BeforeFieldInit |
TypeAttributes.AutoLayout,
typeof(object));
return typeBuilder;
}
}
}
答案 0 :(得分:2)
关于你的第二个问题:
我需要浏览对象图以进行测试。
我想到的最简单的方法是将动态程序集保存到磁盘,然后在ILSpy或其他反编译器中查看它。为此,请为AssemblyBuilderAccess.RunAndSave
方法指定DefineDynamicAssembly
选项,并使用DefineDynamicModule
方法提供文件名:
AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assembly, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assembly.Name,
"temp.dll");
最后添加:
assemblyBuilder.Save("temp.dll");