我是否需要一个包装器 class 用于 p/invoke'ing 来自 user32.dll 的一些函数

Do I need a wrapper class for p/invoke'ing a few functions from user32.dll

所以我正在开发一个 c# Windows 表单应用程序,我的部分代码使用了 user32.dll 中的一些方法。下面列出了它们。

起初我将它们放在文件中,所有主要表单代码作为 public partial class MainForm 的一部分,这一切都有效。然后,当我在 Visual Studio Community 2015 中进行 运行 代码分析时,它抱怨说“因为它们是 P/Invoke 方法,所以它们应该在名为 NativeMethods、SafeNativeMethods 或 UnsafeNativeMethods 的 class 中定义。

所以作为一个优秀的编码员,我总是服从他的突发奇想 IDE 我立即制作了一个新的 class 文件并 运行 进入第一期。

Would the class containing these functions be unsafe (is it also unmanaged)? Which name should I use and should the class be declared as internal static with the [DebuggerNonUserCode] attribute?

当我阅读更多内容以尝试弄清楚这一点时,我不断遇到为代码制作包装器 class 的参考资料,所以我开始研究它。这产生了大量关于 c++ 或 c 的安全性和包装器、原型和大量其他似乎没有帮助的信息,让我完全迷失了方向。

So I guess what I want to know is two things. 1st, would I need to (or would it be best practice to do so) make a wrapper class to use these methods, and if so, how would I go about doing it?

2nd, If I make the class Unsafe/SafeNativeMethods should I call it safe or unsafe? Should all the methods be left public? Or do should have the methods declared private and write some getters/setters like:

public IntPtr getGetForegroundWindow()
{
    return GetForegroundWindow()
}

public setSendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr, lParam)
{
    SendMessage(hWnd, Msg, wParam, lParam);
}

或者我是否需要使用委托或其他东西来代替 setter 和 getter?

抱歉这个问题有点脑残。每次我认为我找到了答案,但我最终都会提出更多问题,safe/unsafe/security 的所有谈话都让我担心。我不介意 google 搜索和阅读主题,但阅读列表只是为了弄清楚要阅读的内容越来越多,所以我想我会停下来问这里看看我是否问了正确的问题。提前致谢。

我会创建一个静态 class。

namespace NativeMethods
{
    public static class User32
    {
        [DllImport("user32.dll")]
        public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 msg, IntPtr wParam, ref RECT lParam);
    }
}

仅在包装器执行某些操作时创建包装器,例如保持参数状态 conversion/checking。


想要包装 pInvokes 的情况

包装 PInvoke 方法的示例可能是当本机方法分配内存和 returns 句柄时。在这种情况下,您需要创建一个包装器来跟踪句柄。它应该实现 IDisposable 以释放非托管资源。

对于(伪)示例:(你应该检查处置模式)

public class MyWrapper : IDisposable
{
    [DllImport("MyLibrary.dll")]
    private static extern IntPtr DoAllocSomeMemory(int size);

    [DllImport("MyLibrary.dll")]
    private static extern void ReleaseMe(IntPtr handle);


    private IntPtr _handle;

    public MyWrapper()
    {
        _handle = DoAllocSomeMemory(8000);
    }

    public void Dispose()
    {
        ReleaseMe(_handle);
    }    
}