托管代码是否应该返回错误或将异常抛给非托管代码?

Ste*_*rdi 5 c# c++ com exception

我将使用COM将使用C#编写的服务公开给传统的C++应用程序.向非托管客户端报告错误的最佳方法是什么?抛出异常或只返回错误值?

谢谢,斯特凡诺

Joe*_*Joe 10

你应该抛出异常.框架将异常映射到HRESULTS,HRESULT是将错误返回给COM客户端的标准方法,因此这是可行的方法.

每个Exception类型都有一个HResult属性.当从COM客户端调用的托管代码抛出异常时,运行时将HResult传递给COM客户端.如果需要特定于应用程序的HRESULT代码,则可以创建自己的自定义异常类型并设置Exception.HResult属性.

需要注意的一点是,当向COM客户端抛出异常时,调用堆栈信息将丢失.因此,在传播到COM客户端之前记录异常是个好主意.

我有时使用的一种技术如下:为COM客户端显式实现一个ComVisible接口,用于记录和重新抛出异常.COM客户端使用ComVisible接口在传播异常之前记录异常..NET客户端使用具体类,并期望自己安排异常处理.编写它有点啰嗦,但在您随后进行故障排除时可能会有所帮助.

此方法的另一个优点是,您可以根据COM客户端的COM限制定制API,并为标准.NET客户端提供更标准的API.例如,COM客户端仅限于通过引用传递数组,而不支持.NET客户端通过引用传递.

例:

[
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
        }
    }

}
Run Code Online (Sandbox Code Playgroud)