如何在.NET Core中发出类型 [英] How to emit a Type in .NET Core

查看:89
本文介绍了如何在.NET Core中发出类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C#中,如何使用.NET Core在运行时发出新的Type?我为.NET 6找到的所有示例似乎都无法在.NET核心中使用(它们都以获取当前的AppDomain开头,而该AppDomain在.NET核心中不再存在).

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 current AppDomain, which doesn't exist in .NET core any more).

如果可能的话,我希望看到一个涉及创建Type并将属性添加到Type的示例.

If possible I would appreciate an example that involves creating a Type and adding a property to the Type.

推荐答案

此处是有关在.NET 4中创建动态类型的文章.

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

如何在C#中动态创建类?

在接受的答案中,仅是 AppDomain 的一种用法.

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

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

这是关于.NET核心中 DefineDynamicAssembly 函数的替换的另一篇SO帖子.

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

在其中是否可以替换AssemblyBuilder.DefineDynamicAssembly.NET Core?

这里是:

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

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

此外, TypeBuilder 也有所不同. CreateType 函数已不存在,要创建类型,我们应该使用 CreateTypeInfo .是的,它还是来自SO post.

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从TypeBuilder中丢失.如何移植呢?

这是工作的修改后的示例(用于.NET核心),用于创建Type并向Type添加属性.

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

这篇关于如何在.NET Core中发出类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆