Реализация IDispatch в c # - PullRequest
6 голосов
/ 09 ноября 2011

Я пишу некоторый тестовый код для эмуляции неуправляемого кода, вызывающий мою реализацию C # позднего связывающего COM-объекта.У меня есть интерфейс, который объявлен как тип IDispatch, как показано ниже.

 [Guid("2D570F11-4BD8-40e7-BF14-38772063AAF0")]
 [InterfaceType(ComInterfaceType.InterfaceIsDual)]
 public interface TestInterface
 {
     int Test();
 }

 [ClassInterface(ClassInterfaceType.AutoDual)]
 public class TestImpl : TestInterface 
 {
 ...
 }

Когда я использую приведенный ниже код для вызова функции GetIDsOfNames IDispatch

  ..
  //code provided by Hans Passant
  Object so = Activator.CreateInstance(Type.GetTypeFromProgID("ProgID.Test"));
  string[] rgsNames = new string[1];
  int[] rgDispId = new int[1];
  rgsNames[0] = "Test";

  //the next line throws an exception
  IDispatch disp = (IDispatch)so;

, где IDispatch определяется как:

 //code provided by Hans Passant
 [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00020400-0000-0000-C000-000000000046")]
 private interface IDispatch {
     int GetTypeInfoCount();
     [return: MarshalAs(UnmanagedType.Interface)]
     ITypeInfo GetTypeInfo([In, MarshalAs(UnmanagedType.U4)] int iTInfo, [In, MarshalAs(UnmanagedType.U4)] int lcid);
     void GetIDsOfNames([In] ref Guid riid, [In, MarshalAs(UnmanagedType.LPArray)] string[] rgszNames, [In, MarshalAs(UnmanagedType.U4)] int cNames, [In, MarshalAs(UnmanagedType.U4)] int lcid, [Out, MarshalAs(UnmanagedType.LPArray)] int[] rgDispId);
  }

Выдается исключение InvalidCastException,Можно ли привести интерфейс ac # в IDispatch?

Ответы [ 2 ]

1 голос
/ 13 марта 2012

Вам необходимо зарегистрировать сборку с помощью regasm, а также пометить классы, к которым вы хотите получить доступ из COM, с помощью атрибута [ComVisible].Вам также может понадобиться сгенерировать и зарегистрировать библиотеку типов, используя tlbexp (для генерации) и tregsvr для ее регистрации.

Также (с точки зрения Win32) «disp = (IDispatch) obj» не совпадает с «disp = obj as IDispatch» - использование оператора «as» фактически вызывает метод QueryInterface для объекта, чтобы получитьуказатель на запрошенный интерфейс, вместо того, чтобы пытаться привести объект к интерфейсу.

Наконец, использование динамического типа c # будет, вероятно, ближе к тому, что другие парни делают для доступа к вашему классу.

1 голос
/ 09 ноября 2011

Вы должны просто иметь возможность использовать отражение для типа COM, чтобы получить список методов.

Type comType = Type.GetTypeFromProgID("ProgID.Test");
MethodInfo[] methods = comType.GetMethods();
...