创建动态嵌套 class 并将其添加为动态类型中的 属性
Create dynamic nested class and adding it as a property in a dynamic Type
嗨,
我正在尝试在给定 xml 的基础上生成 class,为此我使用 Reflection.Emit 并且到目前为止我有以下方法:
private static AssemblyBuilder GetAssemblyBuilder()
{
AssemblyBuilder assemblyBuilder;
AssemblyName assemblyName = new AssemblyName(Constants.ClassGenerator.ASSEMBLY_NAME);
if (Assemblies.TryGetValue(assemblyName, out assemblyBuilder))
{
return assemblyBuilder;
}
AppDomain currentDomain = AppDomain.CurrentDomain; // Thread.GetDomain();
assemblyBuilder = currentDomain
.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
if (!Assemblies.TryAdd(assemblyName, assemblyBuilder))
{
throw new Exceptions.ClassGeneratorException("The assembly cannot be added to the dictionary.");
}
return assemblyBuilder;
}
private static ModuleBuilder GetModuleBuilder(AssemblyBuilder inAssemblyBuilder)
{
ModuleBuilder module = inAssemblyBuilder.DefineDynamicModule(Constants.ClassGenerator.MODULE_NAME,
$"{Constants.ClassGenerator.MODULE_NAME}.dll");
return module;
}
public static FormatBase CreateType(XmlConfiguration inConfiguration)
{
ModuleBuilder module = GetModuleBuilder(GetAssemblyBuilder());
TypeBuilder typeBuilder = module.DefineType(inConfiguration.EdiFactType,
TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.Serializable, typeof (FormatBase));
AddDataContractAttribute(typeBuilder);
//<Adding Properties>
MapProperties(typeBuilder, inConfiguration.XmlProperties);
//<Generate the type>
Type t = typeBuilder.CreateType();
return (FormatBase) Activator.CreateInstance(t);
}
public static void MapProperties(TypeBuilder inTypeBuilder, List<XmlProperty> inProperties)
{
foreach (XmlProperty xmlProperty in inProperties)
{
if (xmlProperty.Children.Any())
{
TypeBuilder newClass = CreateClass(inTypeBuilder, xmlProperty);
MapProperties(newClass, xmlProperty.Children);
newClass.CreateType();
CreateProperty(inTypeBuilder, newClass);
}
else
{
PropertyBuilder propertyElement = CreateProperty(inTypeBuilder, xmlProperty);
}
}
}
public static TypeBuilder CreateClass(TypeBuilder inParentBuilder, XmlProperty inXmlProperty)
{
TypeBuilder typeBuilder = inParentBuilder.DefineNestedType(inXmlProperty.PropertyName, TypeAttributes.Public |
TypeAttributes
.NestedPublic |
TypeAttributes
.Serializable);
AddDataContractAttribute(typeBuilder);
return typeBuilder;
}
到目前为止一切正常,当我尝试将新创建的 class 添加为我正在生成的类型的 属性 时出现问题:
private static PropertyBuilder CreateProperty(TypeBuilder inParentTypeBuilder, TypeBuilder inTypeBuilder)
{
Type propertyType = inTypeBuilder.CreateType();
PropertyBuilder propertyBuilder =
inParentTypeBuilder.DefineProperty(propertyType.Name,
PropertyAttributes.None,
propertyType,
new[] {propertyType});
FieldBuilder field = inParentTypeBuilder.DefineField($"_{propertyBuilder.Name.ToLower()}",
propertyType,
FieldAttributes.Private);
GetMethodBuilder(inParentTypeBuilder, propertyBuilder, field);
SetMethodBuilder(inParentTypeBuilder, propertyBuilder, field);
//SetAttribute(propertyBuilder, inXmlProperty);
return propertyBuilder;
}
抛出一个 System.TypeLoadException,说我的类型无法加载并在我调用 inParentTypeBuilder.DefineProperty 的地方引发。
有好心人-Reflection.emit-大师可以帮帮我吗?
我 "fixed" 它使得 类 没有嵌套。
这不是解决方案,但它有效。
private TypeBuilder CreateClass(XmlProperty inXmlProperty = null)
{
if (inXmlProperty == null)
{
//It's root class (CONTRL; UTILMD; INVOC; ETC)
TypeBuilder rootTypeBuilder = ModuleBuilder.DefineType(Configuration.EdiFactType,
TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.Serializable);
RootClass = rootTypeBuilder;
TypeController.SetClassAttributes(RootClass);
return rootTypeBuilder;
}
//Nested class (Nachricht, Vorgang, etc)
TypeBuilder typeBuilder = ModuleBuilder.DefineType(inXmlProperty.PropertyName, TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.Serializable);
TypeController.SetClassAttributes(typeBuilder, inXmlProperty);
return typeBuilder;
}
嗨, 我正在尝试在给定 xml 的基础上生成 class,为此我使用 Reflection.Emit 并且到目前为止我有以下方法:
private static AssemblyBuilder GetAssemblyBuilder()
{
AssemblyBuilder assemblyBuilder;
AssemblyName assemblyName = new AssemblyName(Constants.ClassGenerator.ASSEMBLY_NAME);
if (Assemblies.TryGetValue(assemblyName, out assemblyBuilder))
{
return assemblyBuilder;
}
AppDomain currentDomain = AppDomain.CurrentDomain; // Thread.GetDomain();
assemblyBuilder = currentDomain
.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
if (!Assemblies.TryAdd(assemblyName, assemblyBuilder))
{
throw new Exceptions.ClassGeneratorException("The assembly cannot be added to the dictionary.");
}
return assemblyBuilder;
}
private static ModuleBuilder GetModuleBuilder(AssemblyBuilder inAssemblyBuilder)
{
ModuleBuilder module = inAssemblyBuilder.DefineDynamicModule(Constants.ClassGenerator.MODULE_NAME,
$"{Constants.ClassGenerator.MODULE_NAME}.dll");
return module;
}
public static FormatBase CreateType(XmlConfiguration inConfiguration)
{
ModuleBuilder module = GetModuleBuilder(GetAssemblyBuilder());
TypeBuilder typeBuilder = module.DefineType(inConfiguration.EdiFactType,
TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.Serializable, typeof (FormatBase));
AddDataContractAttribute(typeBuilder);
//<Adding Properties>
MapProperties(typeBuilder, inConfiguration.XmlProperties);
//<Generate the type>
Type t = typeBuilder.CreateType();
return (FormatBase) Activator.CreateInstance(t);
}
public static void MapProperties(TypeBuilder inTypeBuilder, List<XmlProperty> inProperties)
{
foreach (XmlProperty xmlProperty in inProperties)
{
if (xmlProperty.Children.Any())
{
TypeBuilder newClass = CreateClass(inTypeBuilder, xmlProperty);
MapProperties(newClass, xmlProperty.Children);
newClass.CreateType();
CreateProperty(inTypeBuilder, newClass);
}
else
{
PropertyBuilder propertyElement = CreateProperty(inTypeBuilder, xmlProperty);
}
}
}
public static TypeBuilder CreateClass(TypeBuilder inParentBuilder, XmlProperty inXmlProperty)
{
TypeBuilder typeBuilder = inParentBuilder.DefineNestedType(inXmlProperty.PropertyName, TypeAttributes.Public |
TypeAttributes
.NestedPublic |
TypeAttributes
.Serializable);
AddDataContractAttribute(typeBuilder);
return typeBuilder;
}
到目前为止一切正常,当我尝试将新创建的 class 添加为我正在生成的类型的 属性 时出现问题:
private static PropertyBuilder CreateProperty(TypeBuilder inParentTypeBuilder, TypeBuilder inTypeBuilder)
{
Type propertyType = inTypeBuilder.CreateType();
PropertyBuilder propertyBuilder =
inParentTypeBuilder.DefineProperty(propertyType.Name,
PropertyAttributes.None,
propertyType,
new[] {propertyType});
FieldBuilder field = inParentTypeBuilder.DefineField($"_{propertyBuilder.Name.ToLower()}",
propertyType,
FieldAttributes.Private);
GetMethodBuilder(inParentTypeBuilder, propertyBuilder, field);
SetMethodBuilder(inParentTypeBuilder, propertyBuilder, field);
//SetAttribute(propertyBuilder, inXmlProperty);
return propertyBuilder;
}
抛出一个 System.TypeLoadException,说我的类型无法加载并在我调用 inParentTypeBuilder.DefineProperty 的地方引发。
有好心人-Reflection.emit-大师可以帮帮我吗?
我 "fixed" 它使得 类 没有嵌套。
这不是解决方案,但它有效。
private TypeBuilder CreateClass(XmlProperty inXmlProperty = null)
{
if (inXmlProperty == null)
{
//It's root class (CONTRL; UTILMD; INVOC; ETC)
TypeBuilder rootTypeBuilder = ModuleBuilder.DefineType(Configuration.EdiFactType,
TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.Serializable);
RootClass = rootTypeBuilder;
TypeController.SetClassAttributes(RootClass);
return rootTypeBuilder;
}
//Nested class (Nachricht, Vorgang, etc)
TypeBuilder typeBuilder = ModuleBuilder.DefineType(inXmlProperty.PropertyName, TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.Serializable);
TypeController.SetClassAttributes(typeBuilder, inXmlProperty);
return typeBuilder;
}