使用 SafeHandle 的约束与抽象 class

Constraints vs abstract class using SafeHandle

BCryptNative 中有一个名为 GetInt32Property 的方法。 它具有以下签名:

internal static int GetInt32Property<T>(T algorithm, string property) where T : SafeHandle

此方法仅在T为SafeBCryptAlgorithmHandle or SafeBCryptHashHandle类型时有效。它调用使用这些类型的句柄显式定义的本机方法:

[DllImport("bcrypt.dll", EntryPoint = "BCryptGetProperty", CharSet = CharSet.Unicode)]
internal static extern ErrorCode BCryptGetAlgorithmProperty(SafeBCryptAlgorithmHandle hObject,
                                                            string pszProperty,
                                                            [MarshalAs(UnmanagedType.LPArray), In, Out] byte[] pbOutput,
                                                            int cbOutput,
                                                            [In, Out] ref int pcbResult,
                                                            int flags);

[DllImport("bcrypt.dll", EntryPoint = "BCryptGetProperty", CharSet = CharSet.Unicode)]
internal static extern ErrorCode BCryptGetHashProperty(SafeBCryptHashHandle hObject,
                                                       string pszProperty,
                                                       [MarshalAs(UnmanagedType.LPArray), In, Out] byte[] pbOutput,
                                                       int cbOutput,
                                                       [In, Out] ref int pcbResult,
                                                       int flags);

Microsoft 使用函数指针/委托来指向正确的本机函数。我的问题是,为什么 Microsoft 不直接实现具有以下签名的 GetInt32Property 方法:

internal static int GetInt32Property(SafeHandle algorithm, string property)

使用以下本机方法:

[DllImport("bcrypt.dll", CharSet = CharSet.Unicode)]
internal static extern ErrorCode BCryptGetProperty(SafeHandle hObject,
                                                   string pszProperty,
                                                   [MarshalAs(UnmanagedType.LPArray), In, Out] byte[] pbOutput,
                                                   int cbOutput,
                                                   [In, Out] ref int pcbResult,
                                                   int flags);

这有什么缺点吗? (假设传递给 GetInt32Property 的 SafeHandle 总是 SafeBCryptAlgorithmHandle or SafeBCryptHashHandle)。

我只是想知道为什么微软实现这个相对复杂。

是否必须与:

根据 documentation,class 必须被继承,但是 P/Invoked 函数在给定 SafeHandle 的抽象 class 时是否正确处理它?它是否适当地增加和减少引用计数?

很难说出微软为什么选择以这种或那种方式实现某些东西,但我可以回答你的观点。

  • 代码并不复杂。用法很清楚(类似于 GetInt32Property(algorithm, str).
  • 它不会强制你发送你提到的类型之一,你仍然可以用不同的 class 调用它,只要它实现 SafeHandle.
  • 使用的native方法其实都是一样的。这有点奇怪,但我不是这个特定库的专家,所以这可能是有充分理由的。
  • 像这样的通用方法有一个隐藏的好处。 typeof(T) == typeof(SafeBCryptHashHandle) 类型检查不是在运行时完成的,而是在 JIT 时间完成的。这意味着该方法的执行速度应该比 algorith is SafeBCrypthHashHandle.
  • 等常规运行时检查稍快

SafeHandle class 是一个摘要class。这意味着您不能创建它的实例,但可以继承它。本机函数仅获取编组数据,它们不会获取对对象的真实引用。不用担心引用计数。