首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TypeLoadException通过TypeBuilder在C#中创建类型

TypeLoadException通过TypeBuilder在C#中创建类型
EN

Stack Overflow用户
提问于 2016-01-12 12:26:52
回答 1查看 516关注 0票数 1

我在CreateType方法抛出的异常时遇到了问题。例外和第二个问题在结尾。

代码如下:

定义(工作-我希望如此):

代码语言:javascript
复制
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);

构造函数创建(作品):

代码语言:javascript
复制
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:

代码语言:javascript
复制
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);

并创建类型(作品):

代码语言:javascript
复制
typeBuilder.CreateType();
builder.Save("Emission.dll");

下面是我试图创建的代码:

代码语言:javascript
复制
public class User{
   private string _name;
   public User(string name){
      _name = name;
   }
   public override string ToString(){
      return _name;
   }
}

在上面的ToString反编译之后,如下所示:

代码语言:javascript
复制
.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

我的的另一个问题是为什么

代码语言:javascript
复制
    IL_0007: stloc.0
    IL_0008: br.s IL_000a

    IL_000a: ldloc.0

看起来不像这样(为什么会有跳转):

代码语言:javascript
复制
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、Version=0.0.0.0、Culture=neutral、PublicKeyToken=null‘的类型为“User”的方法’Version=0.0.0.0‘必须是虚拟的,才能在接口或超级类型中实现该方法。

然后,我将方法名从"ToString“更改为"Object.ToString”,但出现了相同的异常。

更新2我想出了什么问题。方法生成器应该有更多的MethodAttributes,如下所示:

代码语言:javascript
复制
            var toStringBuilder = typeBuilder.DefineMethod("ToString", MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual | MethodAttributes.HideBySig, typeof(string), Type.EmptyTypes);

谢谢你的回答。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-01-12 13:00:38

typeBuilder.DefineMethod()调用中的第三个参数应该是typeof(string),而不是null,因为ToString()返回一个字符串。

这个分支很可能是由编译器为调试版本引入的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34743691

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档