.NET 4.0迁移后引用.NET 1.0程序集的System.TypeLoadException

.NET 4.0迁移后引用.NET 1.0程序集的System.TypeLoadException,.net,com,migration,arcgis,.net,Com,Migration,Arcgis,有一个项目已从.NET 3.5迁移到.NET 4.0。该项目有一些对.NET 1.0程序集的引用,这些程序集是COM对象的包装。这些.NET 1.0程序集和COM对象是外部公司的产品。项目将进行编译,但在运行时,软件引用这些1.0程序集中定义的对象的第一个点会引发异常: System.TypeLoadException:无法从程序集“ESRI.MapObjects2.Core,Version=2.4.1.0,Culture=neutral,PublicKeyToken=8fc3cc631e44a

有一个项目已从.NET 3.5迁移到.NET 4.0。该项目有一些对.NET 1.0程序集的引用,这些程序集是COM对象的包装。这些.NET 1.0程序集和COM对象是外部公司的产品。项目将进行编译,但在运行时,软件引用这些1.0程序集中定义的对象的第一个点会引发异常:

System.TypeLoadException:无法从程序集“ESRI.MapObjects2.Core,Version=2.4.1.0,Culture=neutral,PublicKeyToken=8fc3cc631e44ad86”加载结构“ESRI.MapObjects2.Core.ShapeTypeConstants”。

该结构被标记为符合类型等价条件,但它有一个静态或非公共字段。实际的“结构”是一个枚举,在Reflector中,它如下所示:

[Guid(“B027CAB1-6908-11D2-AF98-006097DA3688”)]
公共枚举ShapeTypeConstants
{
moShapeTypeEllipse=0x1a,
moShapeTypeLine=0x16,
moShapeTypeMultipoint=0x18,
moShapeTypePoint=0x15,
moShapeTypePolygon=0x17,
moShapeTypeRectangle=0x19
}

内部异常为null。我可以看到0x80131522(-2146233054)的HRESULT,它表示COR_E_TYPELOAD。我认为我没有丢失任何本机DLL或程序集,因为我们的.NET工作正常(并且它使用相同的代码、相同的引用)


如何修复此异常?有没有一种简单的方法,比如在dll的配置文件中指定requiredRuntime,或者在csproj的参考部分中指定requiredTargetFramework?

如果环境恶劣,那么我也可以玩粗野游戏

如果我们看一下实际的错误消息,它会抱怨“structure”中有一个“static或non-public”字段。所谓的结构实际上是一个枚举。似乎是COM层上的包装器枚举。有几十种不同的包装器枚举,每个值都是显式指定的。每一个枚举还包含一个名为“value_u_u”的私有int变量。更具体地说,它看起来是这样的:
.field private specialname rtspecialname int32值

那么我们为什么不干脆把它们公之于众呢:

  • 使用ildasm反汇编源代码
  • 将私有范围限定符替换为public(如果我没记错的话:替换了49个位置)
  • 最后,我使用修改后的IL中的ilasm编译了一个dll
  • 瞧!生成的dll(ESRI.MapObjects2.Core.dll)是311.296字节,而原始dll是323.584字节,这让我仍然有点怀疑。但如果我用修改过的dll覆盖GAC中的原始dll,一切正常,我们的软件就不会再崩溃了。我不能确认一切都是100%工作的,因为我不知道我们软件的GIS部分。但到目前为止我所做的一切都还可以。 让人担心的是:如果公共变量的存在会改变任何结构布局,它可能会导致枚举值的移动或其他混淆。但希望它不会混淆任何东西。这是一个快速破解,在生产中,需要在安装MapObjects42后覆盖GAC中的ESRI.MapObjects2.Core.dll。唉。
    所以我不一定建议任何人,但它似乎起了作用,它给了我一些满足感,某种复仇的感觉。黑客攻击在一天结束时给了我一点快乐。

    可能是其他人的解决方案:省去供应商提供的.NET包装dll,直接从我们的项目中引用底层COM组件。这是Joe Parker在以下线程中描述的:。“我们使用MapObjects 2.3解决了这个问题,方法是将控件作为COM组件引用,而不是使用MapObjects附带的.NET DLL。从项目中删除ESRI。??引用,然后将引用添加到COM组件“ESRI MapObjects 2.3”“。这用实际将在VS 2010中运行的.NET代码包装COM组件

    然后,对于可视化组件,右键单击工具箱并“选择项”。从“COM组件”选项卡中选择“MapObjects 2.3 Map Control”,然后可以将控件添加到表单中。在我的例子中,我必须将其添加到表单中,然后将其删除,这样VisualStudio才能自动将对“AxMapObjects2”的引用添加到项目中。此引用具有可视控件及其一些支持类型。然后,我用AxMapObjects2.AxMap替换了旧的AxMap引用,并用MapObjects2.Typename替换了其他类型,所有这些都正常工作(至少到目前为止)。”


    我认为他的方法也可以推广到其他类似的情况:“appvendor.NET wrappervendor COM对象“。不幸的是,在我们的情况下,这种方法可能不那么容易,因为我们不仅在应用程序中托管了COM控件,而且在软件的其他模块中,我们还具有导出和导入功能以及其他分散的功能。因此,我不能仅仅在那里引用GUI COM组件,我只需要在其他地方使用一些核心功能。但我想我会分享这个发现,它可能会对其他人有所帮助。我100%确信MapObjects2不会,我们的应用程序将是唯一的受害者。由于更多的项目将迁移到.NET 4.0,并且仍然有一些旧的遗留负担,我们可以面对这个问题。

    给定的
    TypeLoadException
    InnerException
    是什么。MapObjects2是一种停产产品。我希望在那里有一个新的ArcGIS API,但我正在寻找一个更简单的解决方案。。。沙尼:我在我原来的帖子上加了答案。没有InnerException,但我看到了一个HResult。Hans:这是一个供应商线程,有类似的问题,但这家伙没有评论他是如何解决问题的。我正在碰壁:如何:编辑互操作程序集,简单:长期的解决方案是在我的特殊情况下转换到更新的API(ArcGIS)。但这需要比dll黑客更多的工作。