TypeLoadException - Could not load type because the format is invalid

异常发生的背景

这是一段运行时的错误,完整的错误信息如下:

Test method ***.Tests.IpHelperTest.TestMarshalSize threw exception:
System.TypeLoadException: Could not load type '***.Network.Protocol.ConnectionRequest' from assembly '***, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because the format is invalid.

引发错误的代码是一段单元测试的代码:

        [TestMethod]
publicvoid TestMarshalSize()
{
var size
= Marshal.SizeOf(typeof(ConnectionRequest));
Assert.AreEqual(
7, size);
}

其中ConnectionRequest是这样定义的:

    [StructLayout(LayoutKind.Sequential, Pack =1, CharSet = CharSet.Ansi)]
publicclass ConnectionRequest:MessageBase
{
publicbyte ClassID;
public ProtocolVersion ProtocolVersion;
}

异常分析和解决

非常简单的代码,但是报的错误却让人摸不着头脑。起先我以为是dll编译的设置不对,比如测试项目编译为x64,但是被测试的代码库编译成32位的。检查之后,我的项目不存在这个问题。实际上,问题存在于ConnectionRequest父类的定义中。先来看一下MessageBase的定义:

publicabstractclass MessageBase
{
public DataPacketHeader header;
}

我没有为MessageRequest定义StructLayout,因为我并不打算对MessageBase进行Marshal的操作。然而,这似乎不符合C#对Marshal操作的要求,如果要对一个类做Marshal的操作,那么我们必须为它的父类也设置StructLayout即使它的父类里什么都没有。所以要解决TypeLoadException的问题,我们需要对MessageBase设置StructLayout。

发现新问题

但是,我又发现一个问题: 如果我们自定义的一个类不显示地继承其它的类,那它实际上会继承Object类。如果自定义的类要做Marshal,那么Object类也要定义StructLayout了,但是检查Object的定义发现是没有StructLayout的。这是什么回事呢?我没找到相关的文档。

posted @ 2011-09-19 13:35  排骨虾  阅读(1379)  评论(0编辑  收藏  举报