我正在寻找有关更改返回/传递到p / invoke函数的对象的结构/类布局的最佳实践指南。我已经找到了答案,但也许我太累了,而且我没有有效地搜索。
我能提出的最简单的例子(真正的一个在这里有点过于复杂)与GetWindowRect类似。
如果我想为RECT结构添加一些额外的属性,我应该将它添加到结构本身的定义中,还是应该切换到子类化以添加额外的属性?
是否有来自Microsoft或其他可靠来源的最佳做法围绕以下方法?这些都是最佳做法吗?
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left; // x position of upper-left corner
public int Top; // y position of upper-left corner
public int Right; // x position of lower-right corner
public int Bottom; // y position of lower-right corner
public string Extra; // ADDED
}
对战
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
public class RECT
{
public int Left; // x position of upper-left corner
public int Top; // y position of upper-left corner
public int Right; // x position of lower-right corner
public int Bottom; // y position of lower-right corner
}
public class RectEx : RECT
{
public string Extra; // Added
public RectEx(RECT r)
{
Left = r.Left;
Top = r.Top;
Right = r.Right;
Bottom = r.Bottom;
Extra = "test";
}
}
答案 0 :(得分:1)
这是另一个选项:这允许您维护本机功能并为您正在使用的对象提供一些安全性。
// used internally in native method
[StructLayout(LayoutKind.Sequential)]
internal struct RECT
{
public int Left; // x position of upper-left corner
public int Top; // y position of upper-left corner
public int Right; // x position of lower-right corner
public int Bottom; // y position of lower-right corner
}
// public accessible struct with extra fields
public struct RectEx
{
public int Left; // x position of upper-left corner
public int Top; // y position of upper-left corner
public int Right; // x position of lower-right corner
public int Bottom; // y position of lower-right corner
public dynamic Extra = "Extra";
}
public static class UnsafeNativeMethods
{
//used internally to populate RECT struct
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(HandleRef hWnd, out RECT lpRect);
//public safe method with exception handling and returns a RectEx
public static RectEx GetWindowRectangle(HandleRef hWnd)
{
RECT r = new RECT();
RectEx result = new RectEx();
try
{
GetWindowRect(hWnd, r);
result.Left = r.Left;
result.Top = r.Top;
result.Right = r.Right;
result.Bottom = r.Bottom;
// assign extra fields
}
catch(Exception ex)
{
// handle ex
}
return result;
}
}
答案 1 :(得分:0)
您还可以使用: 的 StructLayout(LayoutKind.Explicit)强>
[StructLayout(LayoutKind.Sequential)]
public struct Point
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Explicit)]
public struct Rect
{
[FieldOffset(0)] public int left;
[FieldOffset(4)] public int top;
[FieldOffset(8)] public int right;
[FieldOffset(12)] public int bottom;
}
(来自http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.layoutkind.aspx)