Не удается получить эквивалентность типа для работы с плагином Google Планета Земля - PullRequest
2 голосов
/ 06 июля 2011

У меня есть приложение WinForms C #, в которое встроен плагин Google Планета Земля (GE). Это можно сделать с помощью COM Interop, добавив ссылку на плагин Google Планета Земля.

Мы хотели бы иметь возможность поддерживать разные версии плагина GE при развертывании нашего приложения. Поэтому мы ссылаемся и создаем наше приложение на основе версии 5.0 подключаемого модуля GE на разрабатываемой машине, а затем развертываем на другом компьютере, на котором установлена ​​версия 6.0 подключаемого модуля GE, чтобы приложение запускалось с использованием эквивалентности типов.

Из моего понимания Внедрения Типа и Эквивалентности Типа, включенного в C # 4.0, это именно тот адрес Эквивалентности Типа. Однако я не смог заставить это работать.

Я добавляю ссылку на плагин Google Планета Земля 5.2 в Visual Studio 2010 в качестве ссылки на COM. Я выбираю «Вставить типы взаимодействия»

Затем я запускаю приложение на компьютере с установленным плагином 6.0 GE.

Я получаю исключение, запустив следующую строку кода

string pluginVersion = ge.getPluginVersion();

где ge определяется как

 private IGEPlugin ge;

и 'IGEPlugin' - это интерфейс, определенный COM-взаимодействием для библиотеки DLL плагинов GE.

System.AccessViolationException не было обработано кодом пользователя Сообщение = Попытка чтения или записи в защищенную память. Это часто указывает на то, что> другая память повреждена.

Исключительная ситуация при изменении (сборка с 6.0, запуск с версией 5.2)

Код и приложение работают нормально при сборке и запуске на одной и той же версии плагина GE.

Так что не уверен, что мне не хватает, из документации MSDN может показаться, что он должен работать автоматически.

Эквивалентность типов и встроенные типы взаимодействия

Я действительно надеялся избежать необходимости везде использовать динамический C # 4.0 для обеспечения совместимости между версиями GE Plugin, так как я потерял весь Intellisense и мне пришлось бы изменить много кода.

1 Ответ

2 голосов
/ 13 октября 2011

Я боролся с этим некоторое время.Причина, по которой он не работает с «Embed Interop Types», заключается в том, что Google по какой-то причине генерирует совершенно новый GUID для COM-объекта, что означает, что встроенная библиотека взаимодействия больше не будет функционировать, даже если интерфейс точното же самое.

Я только недавно столкнулся с этой проблемой, когда плагин GoogleEarth решил автоматически обновиться, и таким образом нарушил Interop-Compatibility, имея новый COM-GUID.

Я понимаювы не хотите использовать «динамический» везде, так как вы теряете IntelliSense - я бы посоветовал вам использовать ссылку взаимодействия для начальной разработки, чтобы у вас это было на этом этапе со статической типизацией, а затем переключаться на «динамический», как толькодостаточно стабильный, и вы просто хотите убедиться, что он по-прежнему работает с будущими версиями GoogleEarth без исключения приведения.

Я понимаю, что вы уже знаете, как решить эту проблему с помощью "динамического", но я публикую решениеЯ использовал ниже, может быть, другие люди могли бы использовать его.

С c # 4.0 у вас есть простое решение для этого.Я решил эту проблему, НЕ объявляя "ge" как тип "IGEPlugin" и удаляя все ссылки на GoogleEarth в проекте.Вместо этого объявите "ge" следующим образом:

private dynamic 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);
    }
}

Обратите внимание, что «родительский элемент» в конструкторе - это элемент управления, на котором размещены элемент управления для браузера и плагин.Он получает доступ к держателю плагинов для взаимодействия с GoogleEarth, как только вызывается JSInitSuccessCallback_.Интерфейс для держателя плагинов выглядит следующим образом (больше не уверен, зачем он мне нужен, но все равно все идет):

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