Почему COM-взаимодействие предпочтительнее P / Invoke в .NET?

В нашем проекте мы повторно используем много кода Delphi через COM в нашем приложении asp.net.

Вот так: legacy delphi dll = & gt; Оболочка delphi COM = & gt; .Net interop = & gt; asp.net (mvc)

У нас есть некоторые проблемы, связанные с нарушениями доступа, выгрузкой dll и т. Д. Теперь я перенес некоторые из них, чтобы использовать устаревшую dll напрямую через код P / Invoke.

Когда я смотрю на ресурсы, касающиеся COM и P / Invoke, люди почти всегда советуют использовать COM. Это почему? Не имеет ли P / Invoke следующие преимущества:

checked out code will always use the correct dll‘s instead of the last registered COM Multiple versions can run side by side on the servers (for instance: DEV, TEST and QA) No more COM registrations hassle Much faster than COM communication (articles I read indicate a 30% speed increase)
 Martin Liversage07 июн. 2012 г., 12:48
Используя свободный от регистрации COM (также известный как параллельная регистрация), вы можете избежать пунктов 2 и 3 в своем списке недостатков. Ну, пункт 3 превращается в то, как заставить COM без регистрации делать то, что вы хотите.msdn.microsoft.com/en-us/library/ms973913.aspx
 Govert07 июн. 2012 г., 11:37
Не могли бы вы дать некоторые ссылки, которые предполагают, что COM предпочтительнее P / Invoke? Я очень согласен с вами, что P / Invoke является лучшим решением, если оно доступно. Большинство внутренних компонентов в .NET BCL реализовано с точки зрения P / Invoke для Win32 API. Единственная причина использования COM-взаимодействия - это когда у вас нет выбора, например, взаимодействовать с приложениями Office или частями API Windows, которые предназначены только для COM.
 Panagiotis Kanavos07 июн. 2012 г., 11:37
Помните DLL ад? Вместо использования правильной DLL, ваш код будет использовать первую доступную DLL с тем же именем. Любые изменения API не будут обнаружены до времени выполнения, что означает, что управление версиями практически невозможно. Вы не можете создать DLL, которая будет обслуживать как старых, так и новых клиентов без изменения имен самих функций.
 Ventsyslav Raikov07 июн. 2012 г., 11:35
Вы можете p / вызвать в 32-битной DLL из 64-битного процесса? Я так не думаю.
 Stefan Steiger31 окт. 2012 г., 14:04
Я не предпочитаю COM. Он не является поточно-ориентированным и медленным, ему требуются административные права для установки COM-компонента, а также он совершенно не переносим на другие операционные системы. В общем, я очень предпочитаю компилировать свою dll в x32 и x64 и вызывать нужную, с полным путем к ней, что полностью устраняет dll-ад.

Ответы на вопрос(1)

Решение Вопроса

Pinvoke - очень хороший инструмент, но он не может заменить COM. Pinvoke поддерживает только простые функции с синтаксисом C. COM позволяет реализовать объектную модель. Возьмите, например, классы в пространствах имен Microsoft.Office.Interop, все они являются чистыми классами COM без оболочек. Взаимодействие Office с pinvoke было бы мучительно болезненным.

Другая основная проблема с pinvoke состоит в том, что клиентские программисты обычно пишут декларации. Человек с наименьшей вероятностью понял их правильно. Автор COM может опубликовать автоматически сгенерированную библиотеку типов, очень похожую на метаданные в сборке .NET. Значительное устранение шансов на ошибки и отсутствие необходимости в работе клиентского программиста за пределами Project + Add Reference.

Адресация ваших пуль:

checked out code will always use the correct dll‘s instead of the last registered COM
You are still subject to the vagaries of Windows finding the proper DLL. The only good way to avoid accidents is to store the DLL in the same directory as the EXE. Which is quite possible in COM as well, all you have to do is create an empty file with the name yourapp.exe.local

Multiple versions can run side by side on the servers (for instance: DEV, TEST and QA)
Not a problem in COM either, using the above technique or by using a reg-free manifest

No more COM registrations hassle
Use a reg-free manifest so no registration is required. Very simple to do, just set the Isolated property of the reference to True.

Much faster than COM communication (articles I read indicate a 30% speed increase)
It is much slower than COM. You can incur an extra cost by making late-bound COM calls through IDispatch, that's roughly as expensive as a pinvoke call.

Существует третий способ взаимодействия с собственным кодом: написание оболочки управляемых классов на языке C ++ / CLI. Этот метод широко используется в среде .NET, особенно в mscorlib.dll, System.Data и PresentationFramework, сборках, которые сильно зависят от собственного кода. Однако не очень подходит для Delphi, он лучше всего работает для нативного кода, который можно легко вызвать из C или C ++.

 07 июн. 2012 г., 15:24
Я не знаю, как ответить «это не работает». вопросы. Файл .local просто указывает загрузчику Windows искать только в каталоге, содержащем EXE, независимо от пути, указанного в разделе реестра. Грубый и не заменит манифест, но это, безусловно, может быть удобно.
 08 июн. 2012 г., 15:12
@Cohen: В прошлый раз, когда у меня были проблемы с работой безрегулярного COM, я сделал одноразовый проект VB6, а затем запустил Make My Manifest.
 Cohen07 июн. 2012 г., 15:21
Отличный ответ. Я попробовал манифест без регистрации, но не смог заставить его работать, по крайней мере, не из Visual Studio (изолированное свойство). Я не уверен, как & quot; yourapp.exe.local & quot; меняет поведение поиска правильного COM?
 08 июн. 2012 г., 15:14
Также легко создать его с помощью Visual Studio, установите для свойства Isolated значение true.
 07 июн. 2012 г., 20:17
Замечательные комментарии Но COM без регистрации может быть довольно сложным и ужасным примером того, как сделать COM «проще». Ваш первый пункт об объявлениях верен, но может быть решен автором библиотеки, предоставляющим подписи P / Invoke или даже создающим дружественную для .NET оболочку объектов. И я должен полностью не согласиться с вашим комментарием к производительности. Производительность P / Invoke далеко не близка к позднему связыванию IDispatch. Фактически производительность P / Invoke, C ++ / CLI и (не IDispatch) COM для каждого вызова очень похожа. CLR + JIT довольно умен во всем этом.

Ваш ответ на вопрос