在 C#/VB 中使用 Windows API 结构的 Ansi 和 Unicode 版本的简单方法
Simple way to work with the Ansi and the Unicode version of a Windows API structure in C#/VB
出于互操作的原因,我需要同时使用某些 Windows API 结构 (DEVMODE).
的 ANSI 和 Unicode 版本
有没有办法做到这一点而无需将所有内容声明 两次?目前,我的结构定义如下:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct DevModeAnsi
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public Int16 dmSpecVersion;
// ... lots of other fields ...
public Int16 dmOrientation;
// ... lots of other fields ...
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct DevModeUnicode
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public Int16 dmSpecVersion;
// ... lots of other fields ...
public Int16 dmOrientation;
// ... lots of other fields ...
}
更糟糕的是,我还需要复制所有代码:
bool IsLandscapeOrientation(DevModeAnsi d) { return d.dmOrientation == DMORIENT_LANDSCAPE; }
bool IsLandscapeOrientation(DevModeUnicode d) { return d.dmOrientation == DMORIENT_LANDSCAPE; }
我考虑过以下解决方案:
创建一个公共基础结构:行不通,因为结构不支持继承。
使用通用接口:行不通,因为接口不能包含字段,只能包含属性。因此,我必须为 我想访问的每个字段 创建一个 属性, 四倍 字段列表而不是简单地加倍。
T4:不得已,但我宁愿尽可能避免那种额外的复杂性。
是否有我错过的优雅解决方案?
我将创建一个模板,该模板将接收结构名称并包含字段声明。文件夹将映射到模板。每当执行映射到此功能的给定可执行文件时,它都会生成文件作为输出。该文件夹将被添加到自动加载器并且可执行文件将支持以下命令:
- 添加字段
- 莫菲迪菲尔德
- 删除字段
- 添加结构
- 删除结构
Is there a way to do that without declaring everything twice?
没有
Is there an elegant solution that I've missed?
没有
您可以编写自己的编组代码来序列化此类结构,并增加您想要的灵活性。但所付出的努力将远远超过收益。
出于互操作的原因,我需要同时使用某些 Windows API 结构 (DEVMODE).
的 ANSI 和 Unicode 版本有没有办法做到这一点而无需将所有内容声明 两次?目前,我的结构定义如下:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
struct DevModeAnsi
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public Int16 dmSpecVersion;
// ... lots of other fields ...
public Int16 dmOrientation;
// ... lots of other fields ...
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct DevModeUnicode
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public Int16 dmSpecVersion;
// ... lots of other fields ...
public Int16 dmOrientation;
// ... lots of other fields ...
}
更糟糕的是,我还需要复制所有代码:
bool IsLandscapeOrientation(DevModeAnsi d) { return d.dmOrientation == DMORIENT_LANDSCAPE; }
bool IsLandscapeOrientation(DevModeUnicode d) { return d.dmOrientation == DMORIENT_LANDSCAPE; }
我考虑过以下解决方案:
创建一个公共基础结构:行不通,因为结构不支持继承。
使用通用接口:行不通,因为接口不能包含字段,只能包含属性。因此,我必须为 我想访问的每个字段 创建一个 属性, 四倍 字段列表而不是简单地加倍。
T4:不得已,但我宁愿尽可能避免那种额外的复杂性。
是否有我错过的优雅解决方案?
我将创建一个模板,该模板将接收结构名称并包含字段声明。文件夹将映射到模板。每当执行映射到此功能的给定可执行文件时,它都会生成文件作为输出。该文件夹将被添加到自动加载器并且可执行文件将支持以下命令:
- 添加字段
- 莫菲迪菲尔德
- 删除字段
- 添加结构
- 删除结构
Is there a way to do that without declaring everything twice?
没有
Is there an elegant solution that I've missed?
没有
您可以编写自己的编组代码来序列化此类结构,并增加您想要的灵活性。但所付出的努力将远远超过收益。