views:

39

answers:

1

I have dynamically created the type "FruitTypes" with these two properties

private string _apple;
public string Apple
{ 
    get { return _apple; } 
    set { _apple= value; } 
} 

private string _pear;
public string Pear
{ 
    get { return _pear; } 
    set { _pear= value; } 
}

Now the second type called "Farm" shall have two properties like this:

private string _ID;
public string ID
{ 
    get { return _ID; } 
    set { _ID= value; } 
} 

private ObservableCollection<FruitTypes> _fruits;
public ObservableCollection<FruitTypes> Fruits
{ 
    get { return _fruits; } 
    set { _fruits= value; } 
}

I have no idea how to create the Farm. Can someone please help with with code samples? Many Thanks,

UPDATE: I create the fruitTypes like this:

TypeBuilder typeBldr = modBldr.DefineType("FruitTypes", TypeAttributes.Public | TypeAttributes.Class);

FieldBuilder field = typeBldr.DefineField("_apple", typeof(string), FieldAttributes.Private);

PropertyBuilder propertyBuilder = typeBldr.DefineProperty("Apple", PropertyAttributes.None, typeof(string), new[] { typeof(string) });

MethodAttributes GetSetAttr = MethodAttributes.Public | MethodAttributes.HideBySig;

MethodBuilder currGetPropMthdBldr = typeBldr.DefineMethod("get_Apple", GetSetAttr, typeof(string), Type.EmptyTypes);

ILGenerator currGetIL = currGetPropMthdBldr.GetILGenerator();
currGetIL.Emit(OpCodes.Ldarg_0);
currGetIL.Emit(OpCodes.Ldfld, field);
currGetIL.Emit(OpCodes.Ret);

MethodBuilder currSetPropMthdBldr = typeBldr.DefineMethod("set_Apple", GetSetAttr, null, new[] { typeof(string) });
ILGenerator currSetIL = currSetPropMthdBldr.GetILGenerator();
currSetIL.Emit(OpCodes.Ldarg_0);
currSetIL.Emit(OpCodes.Ldarg_1);
currSetIL.Emit(OpCodes.Stfld, field);
currSetIL.Emit(OpCodes.Ret);

propertyBuilder.SetGetMethod(currGetPropMthdBldr);
propertyBuilder.SetSetMethod(currSetPropMthdBldr);

I do the same thing for a Pear Property within the same type.

Now how to wire them up is like this:

var tempName = new AssemblyName {Name = "MyTempAssembly"};
AssemblyBuilder assemBldr = AppDomain.CurrentDomain.DefineDynamicAssembly(tempName, AssemblyBuilderAccess.Run);
ModuleBuilder modBldr = assemBldr.DefineDynamicModule("MainMod");
Type generetedType = typeBldr.CreateType();

object generetedObject = Activator.CreateInstance(generetedType);
PropertyInfo[] properties = generetedType.GetProperties();

properties[0].SetValue(generetedObject , "Apple", null);
properties[1].SetValue(generetedObject , "Pear", null);
+1  A: 

I assume your core issue is creating the field/property accessors in Farm as ObservableCollection<> with the generic type parameter set to the other dynamic type you just created? The key is to bake the type using TypeBuilder.CreateType() first; like this:

    AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("testassembly"), AssemblyBuilderAccess.Run);

    ModuleBuilder mb = ab.DefineDynamicModule("testmodule");

    TypeBuilder tbFoo = mb.DefineType("FooType");
    TypeBuilder tbBar = mb.DefineType("BarType");

    /* Make our List<FooType> type by baking tbFoo, then setting the result
     * as the generic type parameter for our List<>
     */
    Type tFoo = tbFoo.CreateType();
    Type genListType = typeof(List<>);
    Type listFooType = genListType.MakeGenericType(tFoo);

    /* Now we can define fields/properties of that type */
    FieldBuilder fb = tbBar.DefineField("_foolist", listFooType, FieldAttributes.Public);

    ConstructorInfo ciFooList = listFooType.GetConstructor(System.Type.EmptyTypes);

    ConstructorInfo ciObj = typeof(object).GetConstructor(System.Type.EmptyTypes);

    ConstructorBuilder cb = tbBar.DefineConstructor(MethodAttributes.Public|MethodAttributes.SpecialName|MethodAttributes.RTSpecialName, CallingConventions.Standard, System.Type.EmptyTypes);
    ILGenerator il = cb.GetILGenerator();

    /* Call the base object constructor */
    il.Emit(OpCodes.Ldarg_0);
    il.Emit(OpCodes.Call, ciObj);

    /* Set our _foolist_ field to a new List<FooType> */
    il.Emit(OpCodes.Ldarg_0);
    il.Emit(OpCodes.Newobj, ciFooList);
    il.Emit(OpCodes.Stfld, fb);

    /* Done! */
    il.Emit(OpCodes.Ret);

    /* Now we can bake and create a BarType with its public List<FooType> field
     * set to an empty list of FooTypes
     */
    Type tBar = tbBar.CreateType();
    object oBar = Activator.CreateInstance(tBar);

I use List<T> for the example but it's not much of a stretch to ObservableCollection<T>.

twon33
Thank you so much. I understand it now better. I get it to compile now,but how do I insert values into the instance of my List<> ?Type listFooType = genListType.MakeGenericType(tFoo); object hObject = Activator.CreateInstance(listFooType);How do I set the Properties inside the list<> that is now shown as one whole instance (hObject)? THanks
Kave
More reflection voodoo, unfortunately, but it's pretty straightforward: object oFoo = Activator.CreateInstance(tFoo); object oList = Activator.CreateInstance(listFooType); MethodInfo miListAdd = oList.GetType().GetMethod("Add"); miListAdd.Invoke(oList, new object[] { oFoo });(OT: Can you put code snippets in comments?)
twon33
Thank you so much. It makes now more sense to me. Don't think you can ad proper code snippets into the comment area, but you can always edit your reply and add more code in there. ;)
Kave