Search code examples
c#castingmockingcomautodesk-inventor

suspicious cast there is no type in the solution which is inherited from--> why/somehow it is working


i am currently working on an AddIn for Inventor(3d Modeling Software). When you are using the api there are two different kind of documents

  • AssemblyDocument
  • PartDocument

the api provides me a method which returns the selected document.

   PartDocument part = ((PartDocument)application.ActiveDocument);

during runtime this cast works. The compiler tells me that this is a suspicious cast, because the 'PartDocument' does not implements the type the 'application.ActiveDocument' returns.

 [TypeLibType(TypeLibTypeFlags.FDispatchable)]
  [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
  [Guid("xxxxxx")]
  [DefaultMember("Type")]
  [ComImport]
  public interface PartDocument
  {
....
 [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
  [TypeLibType(TypeLibTypeFlags.FDispatchable)]
  [Guid("xxxxx")]
  [DefaultMember("Type")]
  [ComImport]
  public interface Application
  {...

    [DispId(50331905)]
    _Document ActiveDocument { [DispId(50331905), MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] [return: MarshalAs(UnmanagedType.Interface)] get; }
[Guid("xxxxxx")]
  [CoClass(typeof (_DocumentClass))]
  [ComImport]
  public interface _Document : Document, _VbaImplementationEvents_Event
  {
  }

So why is this working ? Can someone explain this this to me ?

And how can i test this ?

var documentMock =new Mock<PartDocument>();
var applicationMock = new Mock<Application>();
applicationMock.Setup(x => x.ActiveDocument).Returns(documentMock.Object);

The compiler tells me that he cannot cast from 'PartDocument' to '_Document' --> this is true, so why is it working during runtime ?

Thanks in advance


Solution

  • It works because it is a COM type. For COM type casting, the interop handler will automatically call IUnknown.QueryInterface on the COM object (every COM object implements IUnknown) to find out if it supports PartDocument interface, and get the location of the relevant VTable. This is entirely disconnected from the .NET type specification, and, theoretically, could return a different result each time it was called.