2009-05-07 14 views

Respuesta

10

Debe arrojar excepciones. Las excepciones están mapeadas a HRESULTS por el Framework, y HRESULT es la forma estándar de devolver errores a los clientes COM, así que este es el camino a seguir.

Cada tipo de excepción tiene una propiedad HResult. Cuando el código administrado llamado desde un Cliente COM arroja una excepción, el tiempo de ejecución pasa el HResult al cliente COM. Si desea códigos HRESULT específicos de la aplicación, puede crear sus propios tipos de excepción personalizados y establecer la propiedad Exception.HResult.

Un punto a tener en cuenta es que la información de la pila de llamadas se perderá cuando se genere una excepción a un cliente COM. Por lo tanto, puede ser una buena idea registrar excepciones antes de propagar al cliente COM.

Una técnica que a veces uso es la siguiente: implementar explícitamente una interfaz ComVisible para clientes COM que registra y vuelve a lanzar excepciones. Los clientes COM utilizan la interfaz ComVisible que registra las excepciones antes de propagarlas. Los clientes .NET utilizan la clase concreta y se espera que hagan sus propios arreglos para el manejo de excepciones. Es un poco largo para escribir, pero puede ser útil cuando posteriormente se soluciona.

Otra ventaja de este enfoque es que puede tener una API adaptada a las restricciones de COM para clientes COM y una API más estándar para clientes .NET estándar. Por ejemplo, los clientes COM están restringidos a pasar matrices por referencia, mientras que el paso por referencia se desaconseja para los clientes .NET.

Ejemplo:

[ 
ComVisible(true), 
GuidAttribute("..."), 
Description("...") 
] 
public interface IMyComVisibleClass 
{ 
    // Text from the Description attribute will be exported to the COM type library. 

    [Description("...")] 
    MyResult MyMethod(...); 

    [Description("...")] 
    MyOtherResult MyArrayMethod([In] ref int[] ids,...); 
} 
... 
[ 
ComVisible(true), 
GuidAttribute("..."), 
ProgId("..."), 
ClassInterface(ClassInterfaceType.None), 
Description("...") 
] 
public class MyComVisibleClass : IMyComVisibleClass 
{ 
    public MyResult MyMethod(...) 
    { 
     ... implementation without exception handling ... 
    } 

    public MyOtherResult MyArrayMethod(int[] ids,...) 
    { 
     ... input parameter does not use ref keyword for .NET clients ... 
     ... implementation without exception handling ... 
    } 

    MyResult IMyComVisibleClass.MyMethod(...) 
    { 
     // intended for COM clients only 
     try 
     { 
      return this.MyMethod(...); 
     } 
     catch(Exception ex) 
     { 
      ... log exception ... 
      throw; // Optionally wrap in a custom exception type 
     } 
    } 

    MyOtherResult IMyComVisibleClass.MyArrayMethod(ref int[] ids, ...) 
    { 
     // intended for COM clients only 
     try 
     { 
      // Array is passed without ref keyword 
      return this.MyArrayMethod(ids, ...); 
     } 
     catch(Exception ex) 
     { 
      ... log exception ... 
      throw; // Optionally wrap in a custom exception type 
     } 
    } 

} 
1

creo que eso depende de cómo reaccionará el uso de la herencia. Si entiende los valores de retorno de error, entonces vaya con ese enfoque. Si no lo hace, entonces tendrá que lanzar excepciones y esperar que las maneje apropiadamente.

Además, si es una mala referencia (referencia nula por ejemplo) u otro error crítico, siempre lanzaría una excepción. Sin embargo, se deben evitar excepciones para cosas que el consumidor no puede verificar de antemano (por ejemplo, una búsqueda que aparece vacía no debe arrojar una excepción).

3

Si su aplicación COM es compatible con las interfaces IErrorInfo cuando llama a su servicio C# y es un proyecto completamente interno, entonces arrojar excepciones es probablemente la mejor opción ya que captura la mayor cantidad de información. Sin embargo, COM tradicionalmente ha confiado en los resultados de recursos humanos para comunicar los resultados de estado y puede ser mejor si el servicio se va a publicar en otras fuentes.

EDIT: Me gusta la respuesta de Joe mejor.

+0

excepciones se asignan a HRESULTS, así que este es el mejor enfoque. Ver mi respuesta a continuación. – Joe

1

El mejor juez para usar excepciones o valores devueltos sería USTED. "Lanzar excepciones" supera los "valores de retorno" de varias maneras. PERO, en algunos casos, devolver valores sería suficiente.

3

Estoy de acuerdo con los demás en que esta no es una respuesta "sí o no" sin conocer su proyecto íntimamente.

Esto dependerá de una serie de factores tales como:

  • de seguridad (es decir, lo que se debe a su cliente saber sobre su excepción)
  • eficiencia (es decir, es el tiempo de procesamiento crítico)
  • mantenibilidad (es decir, que puede alterar el legado C++ código para analizar sus condiciones de excepción)

Here's a good blog post that discusses a number of subtle points about exception processing.

El autor recomienda cualquiera de los dos enfoques:

O bien:

  • devolver un documento de error.

o:

  • registrar toda la información acerca de la excepción en el servidor.
  • Cree una nueva excepción que haga referencia a la información registrada .
  • Envíe la nueva excepción a el cliente para el procesamiento del lado del cliente y creación de informes.

Personalmente, creo que debe evitar unir estrechamente su servicio C# con su aplicación C++. En otras palabras, escriba su servicio C# para que teóricamente pueda ser utilizado por cualquier consumidor. Del mismo modo, su código C++ debe escribirse para que no dependa del funcionamiento interno del servicio C#, por lo que los cambios o adiciones a las excepciones (o códigos de error) no rompen al consumidor.

Cuestiones relacionadas