2009-09-15 12 views
18

Me refiero a una biblioteca COM en Visual Studio, por lo que ha creado automáticamente el correspondiente conjunto de Interop para mí. Me gustaría hacer un GetType() en estos objetos com, pero siempre devuelven System.__ComObject. Consulta de ellos por una interfaz funciona sin embargo:Cómo obtener el tipo de objeto COM

bool isOfType = someComeObject is ISomeComObject; //this works 

Pero lo que realmente quiero es que esto devolverá el tipo real del objeto COM:

Type type = someComeObject.GetType(); //returns System.__ComObject :-(

¿Alguien sabe cómo hacer lo que quiero hacer ?

Respuesta

39

Agregar referencia a Microsoft.VisualBasic.dll y luego:

Microsoft.VisualBasic.Information.TypeName(someCOMObject) 

referencia MSDN here.

+0

¡Acabo de probar esto y funciona! Sin embargo, no devuelve el nombre completo, solo el nombre de la clase, pero eso está bien para mis propósitos. Miré este método en un reflector que internamente llama 'LegacyTypeNameOfCOMObject' pero no puedo entender lo que realmente hace. –

+0

Ojalá hubiera algo que pudiera darme el nombre completo de ese objeto com para evitar enfrentamientos. –

+0

Gracias. ¿Alguna idea de si esto es posible en C#? – rpattabi

2

Básicamente lo has descubierto. GetType() en un objeto COM le dará System .__ ComObject, y tendrá que intentar convertirlo en otra cosa para ver qué es realmente el objeto.

+0

Hm ... ¿realmente no hay otra manera? Como no puedo probar todos los posibles objetos COM existentes, solo quiero el tipo. La razón es que estoy usando el tipo de un objeto como clave en un diccionario ... –

+2

Muy obvio ... –

+0

La solución de Darin Dimitrov es genial. – catfood

0

Me encontré con esta pregunta hace unos días mientras buscaba el nombre completo de un objeto System.__ComObject. Que terminó siendo el nombre del tipo usando la solución de Darin y luego bucle a través de todas las clases en todos los conjuntos para probar el partido:

typeName = Microsoft.VisualBasic.Information.TypeName(someCOMObject); 
    foreach (System.Reflection.Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) 
    { 
     foreach (Type type in assembly.GetTypes()) 
     { 
      if ((someCOMObject as type)!=null) 
       fullTypeName = type.FullName; 
     } 
    } 
No

la solución más rápida y más elegante, pero funcionó.

+1

'someCOMObject as type'? No estoy seguro si eso funcionaría. – nawfal

+0

Porque no es así. – ensisNoctis

1

La respuesta aceptada por Darin requiere una dependencia a Microsoft.VisualBasic.dll. Si no quiere tener eso, puede usar esta sencilla clase de ayuda:

public static class TypeInformation 
{ 
    public static string GetTypeName(object comObject) 
    { 
     var dispatch = comObject as IDispatch; 

     if (dispatch == null) 
     { 
      return null; 
     } 

     var pTypeInfo = dispatch.GetTypeInfo(0, 1033); 

     string pBstrName; 
     string pBstrDocString; 
     int pdwHelpContext; 
     string pBstrHelpFile; 
     pTypeInfo.GetDocumentation(
      -1, 
      out pBstrName, 
      out pBstrDocString, 
      out pdwHelpContext, 
      out pBstrHelpFile); 

     string str = pBstrName; 
     if (str[0] == 95) 
     { 
      // remove leading '_' 
      str = str.Substring(1); 
     } 

     return str; 
    } 

    [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); 
    } 
} 
+0

Esto parece funcionar también, solo necesita asegurarse de que haya una referencia a 'System.Runtime.InteropServices.ComTypes' para' ITypeInfo' (Visual Studio IDE auto-sugirió 'Microsoft.VisualStudio.OLE.Interop.ITypeInfo', pero esto es _ ** no ** _ ¡el que quieres!) – ErrCode

Cuestiones relacionadas