c# - studio - Cómo emitir un tipo en.NET Core
view component asp.net core (1)
En C #, ¿cómo emito un nuevo Tipo en tiempo de ejecución con .NET Core? Todos los ejemplos que puedo encontrar para .NET 6 no parecen funcionar en el núcleo de .NET (todos comienzan con la obtención del dominio de aplicación actual, que ya no existe en el núcleo de .NET).
Si es posible, apreciaría un ejemplo que implique crear un Tipo y agregar una propiedad al Tipo.
Aquí está la publicación SO sobre la creación de un tipo dinámico en .NET 4.
¿Cómo crear dinámicamente una clase en C #?
Y en la respuesta aceptada es solo un uso de AppDomain
.
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
Aquí hay otra publicación de SO sobre el reemplazo de la función DefineDynamicAssembly
en el núcleo .NET.
¿Hay algún reemplazo de AssemblyBuilder.DefineDynamicAssembly en .NET Core?
Aquí está:
AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString()),AssemblyBuilderAccess.Run);
En "System.Reflection.Emit": "4.0.1"
nuget.
Además, hay una diferencia en TypeBuilder
. CreateType
función CreateType
ya no existe, en lugar de crear tipos, deberíamos usar CreateTypeInfo
. Y sí, es otra vez de SO post.
Falta el tipo de creación en TypeBuilder. ¿Cómo portar esto?
Aquí está trabajando el ejemplo modificado (para .NET core) de crear un Tipo y agregar propiedades al Tipo.
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);
}
}
}