创建动态嵌套类并将其作为动态类型中的属性添加

时间:2017-03-16 15:48:38

标签: c# reflection.emit

HIHO, 我试图在给定的xml的基础上生成一个类,为此我使用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;
    }

到目前为止一切正常,当我尝试将新创建的类添加为类型I生成的属性时出现问题:

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,说我的Type无法加载并在我调用inParentTypeBuilder.DefineProperty的位置上升。

任何好的Samaritan-Reflection.emit-guru可以帮助我吗?

1 个答案:

答案 0 :(得分:0)

我“修复”它使类没有嵌套。

这不是解决方案,但它正在发挥作用。

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;
    }