c# – 在非托管API中统一处理错误代码

我正在编写一个包含相当大的非托管API的包装器.几乎每个导入的方法在失败时都会返回一个常见的错误代码.现在,我这样做:

ErrorCode result = Api.Method();
if (result != ErrorCode.SUCCESS) {
    throw Helper.ErrorToException(result);
}

这很好用.问题是,我有这么多非托管方法调用,这会非常令人沮丧和重复.所以,我尝试切换到这个:

public static void ApiCall(Func<ErrorCode> apiMethod) {
    ErrorCode result = apiMethod();
    if (result != ErrorCode.SUCCESS) {
        throw Helper.ErrorToException(result);
    }
}

这允许我将所有这些调用减少到一行:

Helper.ApiCall(() => Api.Method());

然而,这有两个直接的问题.首先,如果我的非托管方法使用out参数,我必须首先初始化局部变量,因为方法调用实际上是在委托中.我希望能够简单地声明一个目的地而不初始化它.

其次,如果抛出异常,我真的不知道它来自哪里.调试器跳转到ApiCall方法,堆栈跟踪仅显示包含对ApiCall的调用而不是委托本身的方法.由于我可以在单个方法中进行许多API调用,因此调试很困难.

然后我考虑使用PostSharp来包装所有非托管调用以及错误代码检查,但我不确定如何使用extern方法完成.如果它最终只是为每个方法创建一个包装器方法,那么我会遇到与ApiCall方法相同的异常问题,对吧?另外,如果调试器只存在于已编译的程序集中,那么调试器如何知道如何在我的代码中向我显示抛出异常的站点?

接下来,我尝试实现一个自定义封送器,它将拦截API调用的返回值并检查那里的错误代码.遗憾的是,您无法应用自定义封送器来返回值.但我认为如果有效的话,那将是一个非常干净的解决方案.

[return:
    MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(ApiMethod))]
public static extern ErrorCode Method();

现在我完全没有想法.还有什么其他方法可以解决这个问题?

最佳答案 从Visual Studio 2010 SDK中遵循
ErrorHandler类.它存在于早期版本中,但新版本具有
CallWithCOMConvention(Action),根据您的API如何与其他托管代码交互,这可能证明是有价值的.

在可用的方法中,我建议实现以下内容:

>成功(int)
(Failed()只是!Succeeded(),所以你可以跳过它)
> ThrowOnFailure(int)
(为您的返回代码引发适当的例外)
> CallWith_MyErrorCode_Convention(Action)和CallWith_MyErrorCode_Convention(Func< int>)
(比如CallWithCOMConvention,但是你的错误代码)
> IsCriticalException(Exception)
(由CallWith_MyErrorCode_Convention使用)

点赞