3

.NET 3.5 から .NET 4.0 に移行されたプロジェクトがあります。このプロジェクトには、COM オブジェクトのラッパーである .NET 1.0 アセンブリへの参照がいくつか含まれています。これらの .NET 1.0 アセンブリと COM オブジェクトは、外部企業の製品です。プロジェクトはコンパイルされますが、実行時にソフトウェアがこれらの 1.0 アセンブリで定義されたオブジェクトを参照する最初のポイントで例外がスローされます。

System.TypeLoadException: Could not load the structure 'ESRI.MapObjects2.Core.ShapeTypeConstants' from assembly 'ESRI.MapObjects2.Core, Version=2.4.1.0, Culture=neutral, PublicKeyToken=8fc3cc631e44ad86'.

構造体は、型の同等性に適格であるとマークされていますが、静的または非パブリック フィールドがあります。実際の「構造」は列挙型で、Reflector では次のようになります。

[Guid("B027CAB1-6908-11D2-AF98-006097DA3688")] public enum ShapeTypeConstants { moShapeTypeEllipse = 0x1a, moShapeTypeLine = 0x16, moShapeTypeMultipoint = 0x18, moShapeTypePoint = 0x15, moShapeTypePolygon = 0x17, moShapeTypeRectangle = 0x19 }

内部例外は null です。0x80131522 (-2146233054) の HRESULT が表示されます。これは COR_E_TYPELOAD を意味します。私たちの .NET は正常に動作する (同じコード、同じ参照を使用する) ため、ネイティブ dll またはアセンブリが欠落しているとは思いません。

この例外を修正するにはどうすればよいですか? dllの構成ファイルでrequiredRuntimeを指定するか、csprojの参照セクションでrequiredTargetFrameworkを指定するような簡単な方法はありますか?

4

2 に答える 2

0

おそらく他の誰かにとって可能な解決策: ベンダーから提供された .NET ラッパー dll を除外し、基になる COM コンポーネントをプロジェクトから直接参照します。これについては、Joe Parker が次のスレッドで説明しています: http://social.msdn.microsoft.com/Forums/zh-CN/vblanguage/thread/81c44b22-7bdc-4379-b0f6-953e1f96adfe。「MapObjects 2.3 では、MapObjects に付属の .NET dll を使用する代わりに、コントロールを COM コンポーネントとして参照することで、これを解決できました。プロジェクトから ESRI.??? 参照を削除してから、COM コンポーネントへの参照を追加してください」 ESRI MapObjects 2.3".これは、VS 2010 で実際に実行される .NET コードで COM コンポーネントをラップします。

次に、ビジュアル コンポーネントについて、ツールボックスを右クリックし、[アイテムを選択] をクリックします。「COM コンポーネント」タブから「MapObjects 2.3 マップ コントロール」を選択すると、コントロールをフォームに追加できます。私の場合、フォームに追加してから削除する必要があったため、Visual Studio は自動的に "AxMapObjects2" への参照をプロジェクトに追加しました。この参照には、ビジュアル コントロールと、それがサポートする型の一部があります。次に、古い AxMap 参照を AxMapObjects2.AxMap に、他のタイプを MapObjects2.Typename に置き換えただけで、すべてが機能しました (少なくとも今のところは)。"

彼の方法は、「アプリ<->ベンダー.NETラッパー<->ベンダーCOMオブジェクト」など、他の同様の状況にも一般化できると思います。残念ながら、私たちの場合、この方法はそれほど簡単ではないかもしれません。なぜなら、アプリでホストされている COM コントロールがあるだけでなく、ソフトウェアの他のモジュールにもエクスポートおよびインポート機能やその他の散らばったものがあるからです。そのため、そこで GUI COM コンポーネントを参照することはできません。他の場所でコア機能が必要なだけです。しかし、この発見を共有すると思いました。他の人に役立つかもしれません。MapObjects2 ではなく、私たちのアプリだけが犠牲になることは 100% 確信しています。より多くのプロジェクトが .NET 4.0 に移行し、古いレガシーの負担がまだ残っているため、これに直面する可能性があります。

于 2013-04-02T00:40:32.743 に答える
0

ラフな状況なら、私もラフにプレイできます。

実際のエラー メッセージを見ると、「構造」の「静的または非公開」フィールドについて不平を言っています。いわゆる構造体は、実際には列挙型です。一見、COM 層のラッパー列挙型。さらに多くのさまざまなラッパー列挙型があり、それぞれの値が明示的に指定されています。各列挙には、「value__」という名前の 1 つのプライベート int 変数も含まれています。より具体的には、次のようになります。 .field private specialname rtspecialname int32 value__

それでは、単純にそれらを公開してみませんか。

  1. ildasm でソースを逆アセンブルします。
  2. private スコープ修飾子を public に置き換えます (私の記憶が正しければ、49 か所が置き換えられました)。
  3. 最後に、変更された IL から ilasm を使用して dll をコンパイルします。

そして出来上がり!結果の dll (ESRI.MapObjects2.Core.dll) は 311.296 バイトですが、元のものは 323.584 バイトの長さで、まだ少し疑わしいです。しかし、GAC 内の元の dll を変更したもので上書きすると、ソフトウェアが爆発することはなくなります。ソフトウェアの GIS 部分についてよく知らないので、すべてが 100% 機能することを確認することはできません。しかし、これまでに得たものは問題ありません。誰かが心配する可能性があるのは、パブリック変数の存在が構造レイアウトを変更する場合、列挙値のシフトやその他の混乱を引き起こす可能性があることです。しかし、うまくいけば、何も混同しないでしょう。これは簡単なハックであり、本番環境では、MapObjects42 のインストール後に GAC で ESRI.MapObjects2.Core.dll を上書きする必要があります。はぁ。だからと言って誰にでも勧めるわけではありませんが、しかし、それはうまくいくようで、ある種の満足感、ある種の復讐感を私に与えました. ハッキングは、一日の終わりに私に小さな幸せを与えてくれました。

于 2013-04-02T00:22:29.863 に答える