我有一个嵌入Google Earth(GE)插件的WinForms C#应用程序。这是通过COM Interop添加对Google Earth Plugin的引用来完成的。
我们希望能够做的是在部署应用程序时支持不同版本的GE插件。因此,我们在开发机器上引用和构建针对GE插件版本5.0的应用程序,然后部署到另一台安装了GE插件版本6.0的计算机,让应用程序使用类型等效运行。
根据我对C#4.0中包含的类型嵌入和类型等价的理解,这正是Type Equivalence地址。但是,我无法让它发挥作用。
我在Visual Studio 2010中添加了对Google Earth Plugin 5.2的引用作为COM参考。 我选择'嵌入互操作类型'
然后我在安装了6.0 GE插件的机器上运行该应用程序。
运行以下代码行时出现异常
string pluginVersion = ge.getPluginVersion();
其中ge定义为
private IGEPlugin ge;
和'IGEPlugin'是由COM插件DLL定义的接口。
System.AccessViolationException未被用户代码处理 Message =尝试读取或写入受保护的内存。这通常表明>其他内存已损坏。
反转时异常不同(使用6.0构建,针对5.2版运行)
代码和应用程序在构建并运行相同版本的GE插件时工作正常。
所以不确定我缺少什么,从MSDN文档中可以看出它应该自动运行。
Type Equivalence and Embedded Interop Types
我真的希望避免在任何地方切换到使用C#4.0'动态'以获得GE Plugin版本的兼容性,因为我丢失了所有的Intellisense,并且必须更改大量代码。
答案 0 :(得分:2)
我挣扎了一段时间。它不使用“嵌入互操作类型”的原因是Google出于某种原因为COM对象生成了一个全新的GUID,这意味着嵌入的互操作库将不再起作用,即使接口正是如此同样的。
当GoogleEarth插件决定自动更新时,我刚刚遇到了这个问题,从而通过新的COM-GUID打破了Interop兼容性。
我知道你不想在任何地方使用“动态”,因为你失去了智能感知 - 我建议你使用互操作引用进行初始开发,这样你就可以在那个阶段使用静态类型,然后切换到“动态”一旦它足够稳定,你只是想确保它仍然可以使用未来版本的GoogleEarth而不会抛出强制转换异常。
我意识到你已经知道如何用“动态”来解决这个问题,但是我发布了我在下面使用的解决方案,也许其他人可以使用它。
使用c#4.0,您可以轻松解决此问题。我通过不将“ge”声明为类型“IGEPlugin”并删除项目中对GoogleEarth的所有引用来解决此问题。相反,将“ge”声明如下:
private dynamic ge;
现在你可以在ge对象上调用ANY方法,而编译器不必知道它的确切类型。它将在运行时解决。您只需确保使用正确的参数调用正确的方法名称。
如果你可以在没有任何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);
}
}
请注意,构造函数中的“parent”是托管浏览器控件和插件的控件。一旦JSInitSuccessCallback_被调用,它就会访问插件持有者与GoogleEarth进行交互。插件持有者的界面看起来像这样(不再确定为什么我需要它,但无论如何它仍然存在):
[ComVisible(true)]
interface IGoogleEarthJS {
void JSInitSuccessCallback_(object pluginInstance);
void JSInitFailureCallback_(string error);
}