开发者

Reflection: Creating two types, while one type referencing the other type

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 开发者_StackOverflow_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);


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>.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜