Solution:
Ok, basically what I've done was reusing the MyTypeBuilder class (with some adaptations) from the topic below in order to create a dynamic object and added a method to get an IList from it.
Link: How to dynamically create a class in C#?
public class MyObjectBuilder
{
public Type objType { get; set; }
public MyObjectBuilder()
{
this.objType = null;
}
public object CreateNewObject(List<Field> Fields)
{
this.objType = CompileResultType(Fields);
var myObject = Activator.CreateInstance(this.objType);
return myObject;
}
public IList getObjectList()
{
Type listType = typeof(List<>).MakeGenericType(this.objType);
return (IList)Activator.CreateInstance(listType);
}
public static MethodInfo GetCompareToMethod(object genericInstance, string sortExpression)
{
Type genericType = genericInstance.GetType();
object sortExpressionValue = genericType.GetProperty(sortExpression).GetValue(genericInstance, null);
Type sortExpressionType = sortExpressionValue.GetType();
MethodInfo compareToMethodOfSortExpressionType = sortExpressionType.GetMethod("CompareTo", new Type[] { sortExpressionType });
return compareToMethodOfSortExpressionType;
}
public static Type CompileResultType(List<Field> Fields)
{
TypeBuilder tb = GetTypeBuilder();
ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);
// NOTE: assuming your list contains Field objects with fields FieldName(string) and FieldType(Type)
foreach (var field in Fields)
CreateProperty(tb, field.FieldName, field.FieldType);
Type objectType = tb.CreateType();
return objectType;
}
private static TypeBuilder GetTypeBuilder()
{
var typeSignature = "MyDynamicType";
var an = new AssemblyName(typeSignature);
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, 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);
}
}
Also, I used a Field class like so to have information on a particular Field
public class Field
{
public string FieldName;
public Type FieldType;
}
Finally, I found this method somewhere that allows a person to set the value to a Member:
public static void SetMemberValue(MemberInfo member, object target, object value)
{
switch (member.MemberType)
{
case MemberTypes.Field:
((FieldInfo)member).SetValue(target, value);
break;
case MemberTypes.Property:
((PropertyInfo)member).SetValue(target, value, null);
break;
default:
throw new ArgumentException("MemberInfo must be if type FieldInfo or PropertyInfo", "member");
}
}
Afterwards, I did the following to create a dynamic object and insert a property on it:
//Creating a List of Fields (string FieldName, Type FieldType)
List<Field> Fields = new List<Field>();
Fields.Add(new Field { FieldName = "TestName", FieldType = typeof(string) });
//MyObjectBuilder Class
MyObjectBuilder o = new MyObjectBuilder();
//Creating a new object dynamically
object newObj = o.CreateNewObject(Fields);
IList objList = o.getObjectList();
Type t = newObj.GetType();
object instance = Activator.CreateInstance(t);
PropertyInfo[] props = instance.GetType().GetProperties();
int instancePropsCount = props.Count();
for (int i = 0; i < instancePropsCount; ++i)
{
string fieldName = props[i].Name;
MemberInfo[] mInfo = null;
PropertyInfo pInfo = newObj.GetType().GetProperty(fieldName);
if (pInfo != null)
{
var value = pInfo.GetValue(newObj, null);
mInfo = t.GetMember(fieldName);
if (value != null && mInfo != null && !string.IsNullOrEmpty(mInfo[0].ToString()))
SetMemberValue(mInfo[0], instance, value);
}
else
{
mInfo = t.GetMember(fieldName);
if (mInfo != null && !string.IsNullOrEmpty(mInfo[0].ToString()))
SetMemberValue(mInfo[0], instance, null);
}
}
objList.Add(instance);
This solution goes a little bit beyond my initial question, but it does show how to create an object dynamically, hence allowing us to add properties on the fly to that object.