Потребление com-компонента idispatch в C#
Я написал COM - компонент на C++ (6.0-я знаю его старый, но я учусь использовать его), используя интерфейс IDispatch, и пытаюсь использовать его на C#.
Мой код C# выглядит следующим образом:
static void Main(string[] args) { Type type = Type.GetTypeFromProgID("Bens.General.1"); Object obj = Activator.CreateInstance(type); ITest tObj = (ITest)obj; Console.WriteLine("Value1: " + tObj.MyValue()); Console.ReadLine(); }
(Я также пробовал это с помощью dynamic, но и там не повезло).
со следующим интерфейсом ITest:
[Guid("4B8C6960-EB25-11e7-A3BD-001CF0FAD303")] // This matches my IID in Component QueryInterface [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] public interface ITest { [DispId(1)] string MyValue(); [DispId(2)] string Value2(); }
C++ QueryInterface-это:
HRESULT __stdcall Cmpnt::QueryInterface(const IID& iid, void** ppv) { char buffer[37]; char* guid = guid_to_str(&iid, buffer); MessageBox(NULL, guid, guid, 0); if(iid == IID_IUnknown) { *ppv = static_cast<general*>(this); } else if(iid == IID_IDispatch) { *ppv = static_cast<general*>(this); } else if(iid == IID_general) { *ppv = static_cast<general*>(this); } else { *ppv = NULL; return E_NOINTERFACE; } reinterpret_cast<IUnknown*>(*ppv)->AddRef(); return S_OK; }
IID_general определенно соответствует GUID в атрибуте ITest.
Что я уже пробовал:
Он отлично работает в VB6 и VBA (Office 2016), но в C# говорит, что интерфейс
{
4B8C6960-EB25-11e7-A3BD-001CF0FAD303}
Он не реализован, но я точно знаю, что в методе Queryinterface C++ он есть (он работает в VB/VBA, так почему бы и нет C#?)
MessageBox в коде C++ показывает, что C# пытается по крайней мере 10 IID, включая IID_general, который кажется мне странным, но безуспешно. VBA, Excel показывает, что он пробует 6 IID и после этого преуспевает.
Обновление: я обновил свой COM-компонент для поддержки раннего связывания с библиотекой типов, MIDL-генерируемыми интерфейсами и т. д... - опять же, это работает для VBA (Excel), но не в C#.
F-ES Sitecore
Он работает в VB и VBA, поскольку они основаны на COM-языках, поэтому были написаны с нуля для поддержки IDispatch (т. е. они поддерживают как раннее, так и позднее связывание). С c# вся парадигма фреймворка изменилась, чтобы быть строго типизированной, поэтому нет встроенной поддержки таких вещей, как IDispatch. Я считаю, что вы все еще можете получить доступ к методам с помощью reflection\Invoke. Я погуглил "call IDispatch c#" и нашел несколько претендентов, ниже приведен один, но есть и другие, на которые вы тоже можете посмотреть
http://www.productiverage.com/idispatch-iwastedtimeonthis-but-ilearntlots