我正在尝试使用Refle.emit来生成以下类:
public class Parent {
public class Child { }
public Child MyChild { get; set; }
}
所以这就是:
static void Main(string[] args) {
AssemblyName newAssembly = new AssemblyName("myAssembly");
AppDomain appDomain = System.Threading.Thread.GetDomain();
AssemblyBuilder assemblyBuilder =
appDomain.DefineDynamicAssembly(newAssembly, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(newAssembly.Name);
TypeBuilder parentBuilder = moduleBuilder.DefineType("Parent");
TypeBuilder childBuilder = parentBuilder.DefineNestedType("Child");
parentBuilder.DefineProperty("MyProperty", PropertyAttributes.None, childBuilder.CreateType(), null);
parentBuilder.CreateType();
}
我得到一个例外: “无法在parentBuilder.DefineProperty(...,
中从程序集'myAssembly'加载类型'Parent'我没有找到任何方法来创建父类而不在另一个程序集中创建子类。有什么建议吗?
答案 0 :(得分:3)
您可以创建父类而无需在其他程序集中创建子类,实际上您的代码接近正确。在你的代码中,你有一个错误:
parentBuilder.DefineProperty("MyProperty", PropertyAttributes.None, childBuilder.CreateType(), null);
在这里,您尝试使用嵌套类型CreateType
,此时此刻不需要。您只能提供TypeBuilder
:
parentBuilder.DefineProperty("MyProperty", PropertyAttributes.None, childBuilder, null);
但请记住,以这种方式定义属性是不够的。您必须为其setter和getter(可能还有一个支持字段)提供实现。这里有一个生成类的工作示例:
public class Parent
{
public class Child
{
}
private Parent.Child myChild;
public Parent.Child MyChild
{
get
{
return this.myChild;
}
set
{
this.myChild = value;
}
}
}
代码:
TypeBuilder parentBuilder = moduleBuilder.DefineType("Parent", TypeAttributes.Public);
TypeBuilder childBuilder = parentBuilder.DefineNestedType("Child", TypeAttributes.NestedPublic);
PropertyBuilder propertyBuilder = parentBuilder.DefineProperty("MyChild", PropertyAttributes.None, childBuilder, null);
// Define field
FieldBuilder fieldBuilder = parentBuilder.DefineField("myChild", childBuilder, FieldAttributes.Private);
// Define "getter" for MyChild property
MethodBuilder getterBuilder = parentBuilder.DefineMethod("get_MyChild",
MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
childBuilder,
Type.EmptyTypes);
ILGenerator getterIL = getterBuilder.GetILGenerator();
getterIL.Emit(OpCodes.Ldarg_0);
getterIL.Emit(OpCodes.Ldfld, fieldBuilder);
getterIL.Emit(OpCodes.Ret);
// Define "setter" for MyChild property
MethodBuilder setterBuilder = parentBuilder.DefineMethod("set_MyChild",
MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
null,
new Type[] { childBuilder });
ILGenerator setterIL = setterBuilder.GetILGenerator();
setterIL.Emit(OpCodes.Ldarg_0);
setterIL.Emit(OpCodes.Ldarg_1);
setterIL.Emit(OpCodes.Stfld, fieldBuilder);
setterIL.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(getterBuilder);
propertyBuilder.SetSetMethod(setterBuilder);
答案 1 :(得分:0)
在下面的示例中,我删除了Child类型的创建,专注于调试父类型的创建:
public static Type BuildType() {
AssemblyName newAssembly = new AssemblyName("myAssembly");
//AppDomain appDomain = System.Threading.Thread.GetDomain();
AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain
.DefineDynamicAssembly(
newAssembly,
AssemblyBuilderAccess.RunAndSave);
ModuleBuilder moduleBuilder = assemblyBuilder
.DefineDynamicModule(newAssembly.Name, newAssembly.Name + ".dll");
TypeBuilder parentBuilder = moduleBuilder.DefineType(
"Parent", TypeAttributes.Public);
var ctor0 = parentBuilder.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
Type.EmptyTypes);
ILGenerator ctor0IL = ctor0.GetILGenerator();
// For a constructor, argument zero is a reference to the new
// instance. Push it on the stack before pushing the default
// value on the stack, then call constructor ctor1.
ctor0IL.Emit(OpCodes.Ldarg_0);
ctor0IL.Emit(OpCodes.Ldc_I4_S, 42);
ctor0IL.Emit(OpCodes.Call, ctor0);
ctor0IL.Emit(OpCodes.Ret);
//TypeBuilder childBuilder = parentBuilder.DefineNestedType("Child");
//var chType = childBuilder.CreateType();
parentBuilder.DefineProperty(
"MyProperty",
PropertyAttributes.HasDefault,
typeof(string),
//childBuilder.CreateType(),
null);
var type = parentBuilder.CreateType();
assemblyBuilder.Save(newAssembly.Name + ".dll");
return type;
}
我添加了一些东西(包括默认的ctor)。我是从MSDN Assembly Builder得到的。
无论如何,这编译并运行。问题(我强烈怀疑)是你没有在你的代码中完成Child类型。完成子类型,它应该加载正常。由于加载Child时出现问题,因此未加载父。