19

さて、ライブラリが .NET にある場合、COM 経由でアクセスするのは少し無意味であることはわかっていますが、誰かにライブラリを作成して COM 経由で公開するよう依頼すると、人はどの言語でも自由にそうすべきです。

COM ライブラリがどの言語で記述されているかは問題ではありません。

参考までに、.NET ライブラリから生成された .tlb ファイルに対して tlbimp を使用すると、次のようになります。

C:\dev>tlbimp test.tlb
Microsoft (R) .NET Framework Type Library to Assembly Converter 4.0.30319.1
Copyright (C) Microsoft Corporation.  All rights reserved.

TlbImp : error TI1029 : Type library 'test' was exported from
a CLR assembly and cannot be re-imported as a CLR assembly.

さらに、私のテスト用 COM ライブラリは IUnknown を使用しており、事前バインドされた COM 相互運用のみをサポートしています。

4

2 に答える 2

20

tlbimp は問題の始まりに過ぎません。

すべての COM 可視 .NET オブジェクトは IManagedObject を実装します。COM インターフェイスを介してオブジェクトを呼び出そうとするたびに、.NET は IManagedObject に対して QueryInterface を実行し、成功すると、オブジェクトはラップ解除され、代わりに直接アクセスされます。この方法で相互運用呼び出しを排除することは、パフォーマンスの最適化と見なされます。

これは、複数のコンポーネントが .NET 言語で実装される可能性がある COM ベースの相互運用シナリオでは深刻な問題です。各 .NET コンポーネントが独自の tlbimp 生成バージョンの COM インターフェイスを実装する場合、それらはそのインターフェイスを使用して相互に通信できなくなります。インターフェイスの tlbimp された各コピーが同じ COM GUID を持っていても、.NET はそれらを別のインターフェイスと見なします。この問題に対する "正しい" 解決策は、主要な相互運用機能アセンブリで COM インターフェイスを定義し、.NET で実装されたすべてのコンポーネントで同じインターフェイスのコピーを使用することですが、コンポーネント開発者間の調整がなければ、それが起こる可能性はほとんどありません。

この問題は、Microsoft の開発者によってhttp://blogs.msdn.com/b/jmstall/archive/2009/07/09/icustomqueryinterface-and-clr-v4.aspxで強調され、.NET 4 のソリューションと共に取り上げられました。しかし、これはプレリリース バージョンに基づいており、最終版では機能しません。Microsoft によって認められている他の場所については知りません。

1 つの解決策は、.NET から .NET へのシナリオでインターフェイスを放棄し、代わりにリフレクションを使用することです。これは多くの場合うまくいくかもしれませんが、もちろんあまりパフォーマンスが良くありません。おそらく最善の解決策は、アンマネージ コードを使用して各マネージ コンポーネントを集約し、IManagedObject に対する QueryInterface の試行を拒否することです。これは、上記のブログ エントリで説明されていることと似ていますが、そのブログで説明されているように機能しなくなった .NET 機能に依存していません。

.NET 相互運用動作は、IMO ではかなりひどいものであり、明らかに COM ルールに違反しています (同じ IID == 同じインターフェイスであり、オブジェクトが実装されている言語を気にする必要はありません)。しかし、.NET は最初からこのように動作しており、この動作に苦しめられた開発者からのフィードバックが .NET チームの誰も考えを変えたことはありません。

于 2013-03-19T22:11:19.817 に答える
7

Tlbimp は、タイプ ライブラリから、それが .NET アセンブリから生成されたことを確認できます。それはあなたがやろうとしていることをただためらうだけです。.NET アセンブリを使用する場合は、参照を追加するだけです。

レイト バインド COM を使用すると、マシンをだますことができます。C# のdynamicキーワードを使用すると、最も簡単に実行できます。それでも CLR はだまされません。CLR はマネージ アセンブリと相互運用し、実際には COM 呼び出し可能なラッパーを作成しないことがわかります。これは通常、COM サーバーをテストするためのテスト プログラムを作成するために行います。つまり、このテストは実際に COM サーバーが実際に使用される方法をテストしていないということです。バリアントをオブジェクトに変換して元に戻すなどの非常に基本的なことは、まったくテストされません。実稼働環境でアセンブリを使用すると、非常に不愉快な驚きを覚えるかもしれません。

于 2013-02-22T01:10:10.453 に答える