在C#中,如何在运行时使用.NET Core发出新的Type?我可以在.NET 6中找到的所有示例似乎都不适用于.NET内核(它们都是从获取当前AppDomain开始的,而后者在.NET内核中不再存在).
如果可能的话,我将会感谢一个涉及创建Type并向Type添加属性的示例.
这是关于在.NET 4中创建动态类型的帖子.
如何在C#中动态创建一个类?
在接受的答案中只是一个用途AppDomain
.
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
这是关于DefineDynamicAssembly
在.NET核心中替换功能的另一篇SO帖子.
在.NET Core中是否有任何AssemblyBuilder.DefineDynamicAssembly的替换?
这里是:
AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString()),AssemblyBuilderAccess.Run);
在"System.Reflection.Emit": "4.0.1"
nuget.
另外,有区别TypeBuilder
.CreateType
功能不再存在,而是创建我们应该使用的类型CreateTypeInfo
.是的,它再次来自SO帖子.
TypeBuilder中缺少CreateType.如何移植这个?
这是一个工作修改示例(对于.NET核心),用于创建Type并向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() { 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); } } }