I am using System.Reflection in C# to create a dynamic object class at runtime.
This is the example object class that I want to create at runtime.
public class RequestForTest
{
public string variableName { get; set; }
public MyClass myClass { get; set; }
}
For this class, can I set the default value of property name "myClass" like:
public MyClass myClass { get; set; } = new MyClass();
at runtime? And how can I resolve it?
Thank you for your support!
UPDATE
ClassProperty.cs
public class ClassProperty
{
public string? Name { get; set; }
public int Age { get; set; } = 5;
}
My create object class code.
using System.Reflection.Emit;
using System.Reflection;
using SystemReflection;
string className = "ReflectionDemo";
AssemblyName assemblyName = new AssemblyName(className);
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndCollect);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(className + "." + className + ".dll");
TypeBuilder typeBuilder = moduleBuilder.DefineType(className,
TypeAttributes.Public |
TypeAttributes.Class |
TypeAttributes.AutoClass |
TypeAttributes.AnsiClass |
TypeAttributes.BeforeFieldInit |
TypeAttributes.AutoLayout,
null);
// Add a private field of type int (Int32).
FieldBuilder fieldBuilder = typeBuilder.DefineField(
"_name",
typeof(string),
FieldAttributes.Private);
// Next, we build the property. This involves building the property itself, as well as the
// getter and setter methods.
PropertyBuilder pbNumber = typeBuilder.DefineProperty(
"Name", // Name
PropertyAttributes.None,
typeof(string), // Type of the property
new Type[0]); // Types of indices, if any
MethodBuilder mbSetNumber = typeBuilder.DefineMethod(
"set_Name", // Name - setters are set_Property by convention
// Setter is a special method and we don't want it to appear to callers from C#
MethodAttributes.PrivateScope | MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.SpecialName,
typeof(void), // Setters don't return a value
new[] { typeof(string) }); // We have a single argument of type System.Int32
// To generate the body of the method, we'll need an IL generator
ILGenerator il = mbSetNumber.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // Load this
il.Emit(OpCodes.Ldarg_1); // Load the new value
il.Emit(OpCodes.Stfld, fieldBuilder); // Save the new value to this.m_number
il.Emit(OpCodes.Ret); // Return
// Finally, link the method to the setter of our property
pbNumber.SetSetMethod(mbSetNumber);
MethodBuilder mbGetNumber = typeBuilder.DefineMethod(
"get_Name",
MethodAttributes.PrivateScope | MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.SpecialName,
typeof(string),
new Type[0]);
il = mbGetNumber.GetILGenerator();
il.Emit(OpCodes.Ldarg_0); // Load this
il.Emit(OpCodes.Ldfld, fieldBuilder); // Load the value of this.m_number
il.Emit(OpCodes.Ret); // Return the value
pbNumber.SetGetMethod(mbGetNumber);
//////////////////////////////////////////////////////////////////
// Create SystemReflection.ClassProperty
FieldBuilder fieldBuilder1 = typeBuilder.DefineField(
"_classProperty",
typeof(ClassProperty),
FieldAttributes.Private);
// Next, we build the property. This involves building the property itself, as well as the
// getter and setter methods.
PropertyBuilder pbNumber1 = typeBuilder.DefineProperty(
"ClassProperty", // Name
PropertyAttributes.None,
typeof(ClassProperty), // Type of the property
new Type[0]); // Types of indices, if any
MethodBuilder mbSetNumber1 = typeBuilder.DefineMethod(
"set_ClassProperty", // Name - setters are set_Property by convention
// Setter is a special method and we don't want it to appear to callers from C#
MethodAttributes.PrivateScope | MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.SpecialName,
typeof(void), // Setters don't return a value
new[] { typeof(ClassProperty) }); // We have a single argument of type System.Int32
// To generate the body of the method, we'll need an IL generator
ILGenerator il1 = mbSetNumber1.GetILGenerator();
il1.Emit(OpCodes.Ldarg_0); // Load this
il1.Emit(OpCodes.Ldarg_1); // Load the new value
il1.Emit(OpCodes.Stfld, fieldBuilder); // Save the new value to this.m_number
il1.Emit(OpCodes.Ret); // Return
// Finally, link the method to the setter of our property
pbNumber1.SetSetMethod(mbSetNumber1);
MethodBuilder mbGetNumber1 = typeBuilder.DefineMethod(
"get_ClassProperty",
MethodAttributes.PrivateScope | MethodAttributes.HideBySig | MethodAttributes.Public | MethodAttributes.SpecialName,
typeof(ClassProperty),
new Type[0]);
il1 = mbGetNumber1.GetILGenerator();
il1.Emit(OpCodes.Ldarg_0); // Load this
il1.Emit(OpCodes.Ldfld, fieldBuilder); // Load the value of this.m_number
il1.Emit(OpCodes.Ret); // Return the value
pbNumber1.SetGetMethod(mbGetNumber1);
ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public |
MethodAttributes.SpecialName |
MethodAttributes.RTSpecialName, CallingConventions.Standard, Type.EmptyTypes);
//ConstructorInfo? constructorInfo = typeof(object).GetConstructor(Type.EmptyTypes);
ConstructorInfo constructorInfo = typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
ILGenerator constructorILGenerator = constructorBuilder.GetILGenerator();
if (constructorInfo == null)
throw new Exception("Create constructor failed");
constructorILGenerator.Emit(OpCodes.Ldarg_0);
constructorILGenerator.Emit(OpCodes.Call, constructorInfo);
// Set Name
constructorILGenerator.Emit(OpCodes.Ldarg_0);
constructorILGenerator.Emit(OpCodes.Ldstr, "Anh");
constructorILGenerator.Emit(OpCodes.Stfld, fieldBuilder);
// Set ClassProperty
constructorILGenerator.Emit(OpCodes.Ldarg_0);
ConstructorInfo? conInfo = typeof(ClassProperty).GetConstructor(new Type[0]);
if (conInfo == null)
throw new Exception($"Constructor on type {typeof(ClassProperty).Name} not found.");
constructorILGenerator.Emit(OpCodes.Newobj, typeof(ClassProperty));
constructorILGenerator.Emit(OpCodes.Stfld, fieldBuilder1);
constructorILGenerator.Emit(OpCodes.Nop);
constructorILGenerator.Emit(OpCodes.Ret);
var type = typeBuilder.CreateType();
if (type == null)
throw new Exception($"Create type of {className} failed!");
var instanceType = Activator.CreateInstance(type);
//instanceType.GetType().GetProperty("ClassProperty").SetValue(instanceType, Activator.CreateInstance(typeof(ClassProperty)));
//Console.WriteLine("A");
Console.ReadKey();