2011-07-06 6 views
2

Google Earth(GE)プラグインを組み込んだWinForms C#アプリケーションがあります。これは、COM Interop経由で、Google Earthプラグインへの参照を追加することによって行われます。Google Earthプラグインで動作するようにタイプ同値化できません

私たちができることを望むのは、アプリケーションを配備する際にGE Pluginの異なるバージョンをサポートすることです。そこで、我々は開発マシン上のGE Pluginのバージョン5.0に対するアプリケーションを参照して構築し、バージョン6.0のGE Pluginがインストールされている別のマシンに展開し、アプリケーションをタイプ同値性を使って実行させます。

C#4.0に含まれているタイプエンベディングとタイプ同値の理解から、これはまさにタイプ等価アドレスです。しかし、私はこれを動作させることができませんでした。

私は、Visual Studio 2010のGoogle Earthプラグイン5.2への参照をCOMリファレンスとして追加します。 「Interop Interplacement Types」を選択します

次に、6.0 GE Pluginがインストールされたマシンでアプリケーションを実行します。

私はGEが

private IGEPlugin ge; 

のように定義されたコード

string pluginVersion = ge.getPluginVersion(); 

の次の行を実行し、例外を得る「IGEPlugin」はGEプラグインDLLのCOM相互運用機能によって定義されたインターフェースであります。

System.AccessViolationExceptionがユーザーコードによって処理されませんでした。 メッセージ=保護されたメモリを読み書きしようとしました。これは、>他のメモリが壊れていることを示す場合があります。

逆転したときに例外が異なる

(バージョン5.2に対して実行し、6.0でビルド)

コードとアプリケーションの作業罰金構築され、GEプラグインの同じバージョンに対して実行しました。

MSDNのドキュメントから、私は何が不足しているかわからないので、自動的に動作するはずです。私はすべてのインテリセンスを失う、と変更する必要がありますので、私は本当に、GEプラグインのバージョン間の互換性を得るために、C#4.0どこでも「動的」の使用に切り替えることを避けるために期待していた

Type Equivalence and Embedded Interop Types

コードの多く。

+0

http://code.google.com/p/winforms-geplugin-control-library/ – Fraser

答えて

2

私はしばらくの間これで苦労しました。 「Interop型の埋め込み」で動作しない理由は、何らかの理由でGoogleがCOMオブジェクトの完全に新しいGUIDを生成するためです。つまり、インタフェースが正確であっても、埋め込まれたinteropライブラリは機能しなくなります同じ。

GoogleEarthプラグインが自動的に更新され、新しいCOM-GUIDを持つことでInterop-Compatibilityが破られたときに、この問題が発生しました。

私はあなたがIntelliSenseを失ったのでどこからでも「ダイナミック」を使いたくないと思います。最初の開発のための相互参照を使用して静的な型指定をしてからいったん安定していれば、「動的」にして、キャスト例外を投げずにGoogleEarthの今後のバージョンでも機能していることを確認したいだけです。

「ダイナミック」でこれを解決する方法を既に知っていますが、私が下で使用したソリューションを投稿しています。おそらく他の人が使用できるかもしれません。

c#4.0では、これを簡単に解決できます。私は、 "ge"を "IGEPlugin"タイプとして宣言し、プロジェクト内のGoogleEarthへの参照をすべて削除することで、この問題を解決しました。

private dynamic ge; 

今では、コンパイラはそれの正確な型を知らなくても、GEのオブジェクト上の任意のメソッドを呼び出すことができます。その代わり、次のように「GE」を宣言します。実行時に解決されます。あなたは正しいパラメータで正しいメソッド名を呼んでいることを確認する必要があります。

GEPluginへの参照がなくてもプロジェクトをコンパイルすることができたら、正しい軌道に乗っています。このように変更したら、GoogleEarthプラグインのバージョンで私の仕事ができました。

私は、ブラウザコントロールに埋め込まれたプラグインをカプセル化するために使用しているクラスを投稿します:コンストラクタでの「親」は、ブラウザコントロールを制御ホストしていることを

[ComVisible(true)] 
public class GoogleEarthWebPluginHolder : IGoogleEarthJS { 
    dynamic ge = null; 
    GoogleEarthWebViewer parent; 

    public GoogleEarthWebPluginHolder(GoogleEarthWebViewer parent) { 
     this.parent = parent; 
    } 

    public dynamic Plugin { 
     get { 
      return ge; 
     } 
    } 

    public void JSInitSuccessCallback_(object pluginInstance) { 
     ge = (dynamic)pluginInstance; 
     this.parent.JSInitSuccessCallback(); 
    } 

    public void JSInitFailureCallback_(string error) { 
     MessageBox.Show("Error: " + error, "Plugin Load Error", MessageBoxButton.OK, MessageBoxImage.Exclamation); 
    } 
} 

注意をし、プラグイン。 JSInitSuccessCallback_が呼び出されるとすぐに、プラグインホルダにアクセスしてGoogleEarthとやり取りします。 (私はそれを必要とする理由はもうわからないが、ここでは、とにかく行く)プラグインホルダー用のインタフェースは次のようになります。

[ComVisible(true)] 
interface IGoogleEarthJS { 
    void JSInitSuccessCallback_(object pluginInstance); 
    void JSInitFailureCallback_(string error); 
} 
+0

http://code.google.com/p/winforms-geplugin-control-library/ – Fraser

関連する問題