문제

I'm writing some test code to emulate unmanaged code calling my c# implementation of a late binding COM object. I have an interface that is declared as an IDispatch type as below.

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

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

When I use the code below to call IDispatch's GetIDsOfNames function

  ..
  //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;

Where IDispatch is defined as:

 //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);
  }

An InvalidCastException is thrown. Is it possible to cast a c# interface into IDispatch?

도움이 되었습니까?

해결책

You need to register you assembly with regasm, and you need to mark the classes you want to access from COM with the [ComVisible] attribute. You may also need to generate and register a type-library using tlbexp (to generate) and tregsvr to register it.

Also (from a Win32 perspective) "disp = (IDispatch) obj" is not the same as "disp = obj as IDispatch" - using the 'as' operator actually calls the QueryInterface method on the object to get the pointer to the requested interface, instead of trying to cast an object to to the interface.

Lastly using c#'s 'dynamic' type will probably be closer to what the other guys are doing to access your class.

다른 팁

You should just be able to use reflection on the COM type to get the list of methods.

Type comType = Type.GetTypeFromProgID("ProgID.Test");
MethodInfo[] methods = comType.GetMethods();
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top