反射:创建两种类型,而一种类型引用另一种类型

时间:2010-08-18 13:02:09

标签: .net reflection

我已经使用这两个属性动态创建了“FruitTypes”类型

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

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

现在第二种叫做“Farm”的类型应该有两个属性:

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; } 
}

我不知道如何创建农场。 有人可以帮忙处理代码示例吗? 非常感谢,

更新:我创建了这样的fruitTypes:

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);

我对同一类型的Pear属性做同样的事情。

现在如何连接它们就像这样:

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 个答案:

答案 0 :(得分:1)

我假设您的核心问题是在Farm中创建字段/属性访问器ObservableCollection<>,并将泛型类型参数设置为您刚刚创建的其他动态类型?关键是首先使用TypeBuilder.CreateType()烘焙类型;像这样:

    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);

我使用List<T>作为示例,但ObservableCollection<T>并没有太多延伸。