How to emit a Type in .NET Core

前端 未结 1 822
栀梦
栀梦 2020-12-24 01:23

In C#, how do I emit a new Type at runtime with .NET Core? All of the examples I can find for .NET 6 don\'t seem to work in .NET core (they all begin with getting the curren

相关标签:
1条回答
  • 2020-12-24 01:59

    Here is SO post about creating a dynamic type in .NET 4.

    How to dynamically create a class in C#?

    And in the accepted answer is just one use of AppDomain.

    AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
    

    Here is another SO post about a replacement of DefineDynamicAssembly function in .NET core.

    Is there any replace of AssemblyBuilder.DefineDynamicAssembly in .NET Core?

    Here it is:

    AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString()),AssemblyBuilderAccess.Run);
    

    In "System.Reflection.Emit": "4.0.1" nuget.

    Also, there is a difference in TypeBuilder. CreateType function no longer exist, instead for creating types we should use CreateTypeInfo. And yes, it is again from SO post.

    CreateType missing from TypeBuilder. How to port this?

    Here is working modified example (for .NET core) of creating a Type and adding properties to the Type.

    using System;
    using System.Collections.Generic;
    using System.Reflection.Emit;
    using System.Reflection;
    
    namespace ConsoleApp1
    {
        public class FieldDescriptor
        {
            public FieldDescriptor(string fieldName, Type fieldType)
            {
                FieldName = fieldName;
                FieldType = fieldType;
            }
            public string FieldName { get; }
            public Type FieldType { get;  }
        }
    
        public static class MyTypeBuilder
        {
            public static object CreateNewObject()
            {
                var myTypeInfo = CompileResultTypeInfo();
                var myType = myTypeInfo.AsType();
                var myObject = Activator.CreateInstance(myType);
    
                return myObject;
            }
    
            public static TypeInfo CompileResultTypeInfo()
            {
                TypeBuilder tb = GetTypeBuilder();
                ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
    
                var yourListOfFields = new List<FieldDescriptor>()
                {
                    new FieldDescriptor("YourProp1",typeof(string)),
                    new FieldDescriptor("YourProp2", typeof(int))
                };
                foreach (var field in yourListOfFields)
                    CreateProperty(tb, field.FieldName, field.FieldType);
    
                TypeInfo objectTypeInfo = tb.CreateTypeInfo();
                return objectTypeInfo;
            }
    
            private static TypeBuilder GetTypeBuilder()
            {
                var typeSignature = "MyDynamicType";
                var an = new AssemblyName(typeSignature);
                var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString()), 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 void 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();
                Label modifyProperty = setIl.DefineLabel();
                Label exitSet = setIl.DefineLabel();
    
                setIl.MarkLabel(modifyProperty);
                setIl.Emit(OpCodes.Ldarg_0);
                setIl.Emit(OpCodes.Ldarg_1);
                setIl.Emit(OpCodes.Stfld, fieldBuilder);
    
                setIl.Emit(OpCodes.Nop);
                setIl.MarkLabel(exitSet);
                setIl.Emit(OpCodes.Ret);
    
                propertyBuilder.SetGetMethod(getPropMthdBldr);
                propertyBuilder.SetSetMethod(setPropMthdBldr);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题