我在使用CreateType方法引发的欠读异常时遇到问题。 最后是例外和第二个问题。
代码如下:
定义(有效 - 我希望):
AssemblyName name = new AssemblyName("MyOwnNewAssembly");
AssemblyBuilder builder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder moduleBuilder = builder.DefineDynamicModule("Emission", "Emission.dll");
TypeBuilder typeBuilder = moduleBuilder.DefineType("User", TypeAttributes.Public);
typeBuilder.SetParent(typeof(object));
var field = typeBuilder.DefineField("name", typeof(string), FieldAttributes.Private);
构造函数创建(工作):
var constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Any, new Type[] { typeof(String) });
var baseConstructor = typeof(object).GetConstructor(BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Instance, null, new Type[0], null);var genertaor = constructor.GetILGenerator();
genertaor.Emit(OpCodes.Ldarg_0);
genertaor.Emit(OpCodes.Call, baseConstructor);
genertaor.Emit(OpCodes.Nop);
genertaor.Emit(OpCodes.Nop);
genertaor.Emit(OpCodes.Ldarg_0);
genertaor.Emit(OpCodes.Ldarg_1);
genertaor.Emit(OpCodes.Stfld, field);
genertaor.Emit(OpCodes.Ret);
现在这里的代码不起作用 - 覆盖ToString:
var method = typeof(object).GetMethod("ToString");
var toStringBuilder = typeBuilder.DefineMethod("ToString", MethodAttributes.Public, typeof(string), Type.EmptyTypes);
typeBuilder.DefineMethodOverride(toStringBuilder, method);
var generator2 = toStringBuilder.GetILGenerator();
generator2.Emit(OpCodes.Nop);
generator2.Emit(OpCodes.Ldarg_0);
generator2.Emit(OpCodes.Ldfld, field);
generator2.Emit(OpCodes.Stloc_0);
generator2.Emit(OpCodes.Ldloc_0);
generator2.Emit(OpCodes.Ret,field);
并创建类型(作品):
typeBuilder.CreateType();
builder.Save("Emission.dll");
以下是我要创建的代码:
public class User{
private string _name;
public User(string name){
_name = name;
}
public override string ToString(){
return _name;
}
}
在ToString上面反编译后看起来像:
.method public hidebysig virtual
instance string ToString () cil managed
{
.maxstack 1
.locals init (
[0] string
)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld string AssemblyBuilding.User::_name
IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
IL_000b: ret
} // end of method User::ToString
我的其他问题是
的原因 IL_0007: stloc.0
IL_0008: br.s IL_000a
IL_000a: ldloc.0
看起来不像这样(为什么会有跳跃):
IL_0007: stloc.0
IL_000a: ldloc.0
例外是:
发生了'System.TypeLoadException'类型的未处理异常 mscorlib.dll中
附加信息:正文签名和方法实现中的声明不匹配。输入:'用户'。汇编:'MyOwnNewAssembly, Version = 0.0.0.0,Culture = neutral,PublicKeyToken = null'。
更新 我用字符串返回函数更正了上面的代码。现在它几乎可以工作,但我得到另一个异常,表明ToString不是虚拟的。
发生了'System.TypeLoadException'类型的未处理异常 mscorlib.dll中
附加信息:来自程序集MyOwnNewAssembly的'User'类型的方法'ToString', 版本= 0.0.0.0,Culture = neutral,PublicKeyToken = null'必须是虚拟的才能在接口或超类型中实现该方法。
然后我将方法名称从“ToString”更改为“Object.ToString”,但出现了相同的异常。
更新2 我想是什么问题。方法构建器应该有更多的MethodAttributes,如下所示:
var toStringBuilder = typeBuilder.DefineMethod("ToString", MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig, typeof(string), Type.EmptyTypes);
感谢您的回答。
答案 0 :(得分:2)
typeBuilder.DefineMethod()
来电中的第三个参数应该是typeof(string)
而不是null
,因为ToString()
会返回一个字符串。
分支很可能是由编译器为调试版本引入的。