IsAssignableFrom with COM

I work with COM-API, Autodesk Inventor.

This test passes:

[Test] public void CastTest() { Inventor.Document document = _application.ActiveDocument; var assemblyDocument = (Inventor.AssemblyDocument)document; Assert.NotNull(assemblyDocument); } 

This test fails:

 [Test] public void IsAssignableFromTest() { Assert.IsTrue(typeof(Inventor.Document).IsAssignableFrom(typeof(Inventor.AssemblyDocument))); } 

I don’t know anything about COM at all, is there a way to verify that one type of COM β€œinherits” another using reflection or some kind of COM voodoo?

+1
source share
2 answers

A system like COM is not compatible with .NET. Instead, you program against wrappers (called RCWs). To test whether one COM object can be converted to another, COM provides a QueryInterface measure as a member of IUnknown , which each COM object must implement. However, .NET hides this data for you, so you can write COM code that "feels" like .NET code.

If you look at disassembling the Inventors Interop library, you will realize that there is no direct connection between Document and AssemblyDocument . Both are interfaces that only implement the default interface of their respective subclauses and are assigned using CoClassAttribute . But in their inheritance tree they are not directly related to each other. They can implement the same interface (I think something like IDocument ), but you also cannot convert the WinForms button to a picture window, even if they both implement a Control -interface.

This is what reflection and IsAssignableFrom : the metadata that each type of CLR provides. COM works here. Each COM object can "solve" it if it can be called from another interface. To do this, it implements QueryInterface . And for this you need to create an instance of your source type before you can run your test (COM does not know the static members).

A traditional listing calls QueryInterface , so your test might look like this:

 [Test] public void IsAssignableFromTest() { Assert.IsNotNull(_application.ActiveDocument as Inventor.AssemblyDocument); } 

Otherwise, you can call QueryInterface directly through the Marshal class.

However, it is not possible to verify metadata types by reflection with COM objects.

+3
source

If you want to use the Inventor API, you can check the type of the document before sending it to another type.

Example: (VBA)

 Dim oDoc As Document Dim oAssyDoc As AssemblyDocument Set oDoc = ThisApplication.ActiveDocument If oDoc.DocumentType = DocumentTypeEnum.kAssemblyDocumentObject Then Set oAssyDoc = oDoc End If 

Yours faithfully,

+1
source

Source: https://habr.com/ru/post/989516/


All Articles