Short answer: using System.Reflection.Emit
.
Long answer: Is this answer here, but I won’t just stick it to you here. I’ll explain the principle.
First you need to define the dynamic type builder. The answer defines it below (I modified it a little with some things):
private static TypeBuilder GetTypeBuilder(string libraryName = "MainModule", string typeSignature = "MyDynamicType")
{
var an = new AssemblyName(typeSignature); // Aqui você vai definir o nome da classe dinâmica
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(libraryName); // Aqui vai definir em qual Class Library sua classe dinâmica vai estar
TypeBuilder tb = moduleBuilder.DefineType(typeSignature,
TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.AutoClass |
TypeAttributes.AnsiClass |
TypeAttributes.BeforeFieldInit |
TypeAttributes.AutoLayout,
null);
return tb;
}
Next, we can put the method that creates properties. It needs the TypeBuilder
previously assembled for operation:
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);
}
You will probably have to modify your dictionary to receive one Type
instead of string
.
The following is the method that compiles the dictionary in the dynamic class:
public static Type CompileResultType(Dictionary<string, Type> dicionario) // Repare que já mudei aqui pra você
{
TypeBuilder tb = GetTypeBuilder(); // Aqui constrói a classe num Assembly "MainModule.dll", classe "MyDynamicType".
// Parametrize da forma que achar melhor.
ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
foreach (KeyValuePair<string, Type> chaveValor in dicionario)
CreateProperty(tb, chaveValor.Key, chaveValor.Value);
Type objectType = tb.CreateType();
return objectType;
}
Finally, the static method that invokes all others:
public static object CreateNewObject(Dictionary<string, Type> dicionario)
{
var myType = CompileResultType(dicionario);
return Activator.CreateInstance(myType);
}
Use:
var meuObjetoCriadoDiamicamente = MyTypeBuilder.CreateNewObject(dicionario);
Dynamic or static class? What version of C# are you using?
– Maniero
You accepted an answer that generates a static, so I didn’t understand.
– Maniero