问题描述
在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.
在接受的答案中,仅是 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中发出类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!