Estoy referencia a una biblioteca COM en Visual Studio, por lo que se ha creado automáticamente el correspondiente ensamblado de Interoperabilidad para mí. Me gustaría hacer un GetType() en estos objetos com, pero siempre regresan System.__ComObject. Consulta para una interfaz que funciona a pesar de que:

bool isOfType = someComeObject is ISomeComObject; //this works

Pero lo que realmente quiero es esto para regresar el tipo real del objeto com:

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

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

InformationsquelleAutor | 2009-09-15

4 Comentarios

  1. 52

    Agregar referencia a Microsoft.VisualBasic.dll y luego:

    Microsoft.VisualBasic.Information.TypeName(someCOMObject)

    Referencia de MSDN aquí.

    • Acabo de probar esto y funciona! No se devuelve el nombre completo, aunque, sólo el nombre de la clase, pero que está muy bien para mis propósitos. Miré a este método en el reflector que internamente llamadas ‘LegacyTypeNameOfCOMObject’ pero no puedo averiguar lo que realmente hace.
    • Me gustaría que hubiera algo que me pudiera dar el nombre completo de ese objeto com para evitar enfrentamientos.
    • Gracias. Alguna idea de si esto es posible en C#?
    • Microsoft.VisualBasic.dll es una .NETO de la asamblea que se puede consultar y utilizar en todas las aplicaciones.
    • Ver si tiene un componente COM escrito en C++/ATL. Usted podría obtener un resultado diferente de lo que usted espera.
    • Exactamente lo que estaba buscando. Gracias!
    • código Fuente para TypeName

  2. 10

    La aceptó responder por Darin requiere de una dependencia a Microsoft.VisualBasic.dll. Si usted no desea que usted puede usar esta sencilla clase auxiliar:

    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);
    }
    }
    • Esto parece funcionar demasiado – sólo necesita para asegurarse de que hay una referencia a System.Runtime.InteropServices.ComTypes para ITypeInfo (IDE de Visual Studio auto-sugirió Microsoft.VisualStudio.OLE.Interop.ITypeInfo, pero esto es no el que quieras!)
  3. 2

    Que, básicamente, ha descubierto. GetType() en un objeto COM que se va a dar del Sistema.__ComObject, y hay que tratar de convertirlo a algo más, a ver lo que el objeto es en realidad.

    • Hm..¿hay realmente ninguna otra forma? Porque no puedo probar para cada posible objeto COM existentes, sólo quiero que el tipo. La razón es que estoy utilizando el tipo de un objeto como una clave en un diccionario…
    • Bastante obvio…
    • Darin Dimitrov, la solución es muy grande.
  4. -2

    Me topé con esta pregunta hace unos días, mientras estaba buscando el nombre completo del tipo de una System.__ComObject objeto. Acabé el nombre del tipo de uso de Darin solución y, a continuación, recorre todas las clases en todas las asambleas 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 es la más rápida y la solución más elegante, pero funcionó.

    • someCOMObject as type? No sé si esto iba a funcionar.
    • Porque no.
    • ¿por qué no? Está tratando de lanzar «someCOMObject» para el tipo «tipo». Si se produce un error (y sólo entonces), el resultado es null. Si no, entonces es encontrar el tipo correcto. (Lo sé, me tomó un par de días para que conteste :-P)
    • no es un tipo/clase en el código, es una instancia de un tipo. as palabra clave funciona en un tipo

Dejar respuesta

Please enter your comment!
Please enter your name here