将 UnmanagedType 枚举的值转换为其等效的托管类型
Translate values of UnmanagedType enumeration to their managed type equivalents
我正在尝试为 P/Invoking 执行此辅助函数,目的是帮助确定哪种托管类型最适合为 windows [=26= 的特定封送处理声明]定义。
我从这里获取信息:UnmanagedType Enumeration
在 C# 或 Vb.Net 中,我寻求帮助以填补空白案例并修复我当前的错误(如果有)。
(另外,作为一个可选的和定向的问题来回答或不回答:你认为写相反的东西可靠吗?,一种ManagedTypeToUnmanagedTypeEnum
功能。)
Public Shared Function UnmanagedTypeToManagedType(ByVal [type] As UnmanagedType) As Type
Select Case [type]
Case UnmanagedType.AnsiBStr
Return GetType(String)
Case UnmanagedType.AsAny
Return GetType(Object)
Case UnmanagedType.BStr
Return GetType(String)
Case UnmanagedType.Bool
Return GetType(Boolean)
Case UnmanagedType.ByValArray
Case UnmanagedType.ByValTStr
Case UnmanagedType.Currency
Return GetType(Decimal)
Case UnmanagedType.CustomMarshaler
Return GetType(Object)
Case UnmanagedType.Error
Return GetType(IntPtr)
Case UnmanagedType.FunctionPtr
Return GetType([Delegate])
Case UnmanagedType.I1
Return GetType(SByte)
Case UnmanagedType.I2
Return GetType(Short)
Case UnmanagedType.I4
Return GetType(Integer)
Case UnmanagedType.I8
Return GetType(Long)
Case UnmanagedType.IDispatch
Return GetType(IntPtr)
Case UnmanagedType.Interface
Return GetType(IntPtr)
Case UnmanagedType.IUnknown
Return GetType(IntPtr)
Case UnmanagedType.LPArray
Return GetType(IntPtr)
Case UnmanagedType.LPStr
Return GetType(StringBuilder)
Case UnmanagedType.LPStruct
Return GetType(IntPtr)
Case UnmanagedType.LPTStr
Return GetType(String)
Case UnmanagedType.LPWStr
Return GetType(String)
Case UnmanagedType.R4
Case UnmanagedType.R8
Case UnmanagedType.SafeArray
Case UnmanagedType.Struct
Case UnmanagedType.SysInt
Return GetType(IntPtr)
Case UnmanagedType.SysUInt
Return GetType(UIntPtr)
Case UnmanagedType.TBStr
Return GetType(String)
Case UnmanagedType.U1
Return GetType(Byte)
Case UnmanagedType.U2
Return GetType(UShort)
Case UnmanagedType.U4
Return GetType(UInteger)
Case UnmanagedType.U8
Return GetType(ULong)
Case UnmanagedType.VariantBool
Return GetType(Boolean)
Case UnmanagedType.VBByRefStr
Return GetType(String)
Case Else
Throw New InvalidEnumArgumentException(argumentName:="type", invalidValue:=[type],
enumClass:=GetType(UnmanagedType))
Return Nothing
End Select
End Function
对于这样的直接function-liketranslation/mapping(即每个唯一的X
恰好有一个Y
的值) ,我建议使用 Dictionary
而不是 switch
case
VB.Net/C#
Dim unToManagedDict As New Dictionary(Of UnmanagedType, Type) 'VB.Net
Dictionary<UnmanagedType, Type> unToManagedDict = new Dictionary<UnmanagedType, Type>(); //C#
然后在您的应用程序的第一次加载中列出您的 UnmanagedType
enum
,如下所示:
VB.Net/C#
unToManagedDict.Add(UnmanagedType.AnsiBStr, GetType(String)) 'VB.Net
unToManagedDict.Add(UnmanagedType.AsAny, GetType(Object)) 'VB.Net
'and so on... or,
unToManagedDict.Add(UnmanagedType.AnsiBStr, typeof(string)); //C#
unToManagedDict.Add(UnmanagedType.AsAny, typeof(object)); //C#
//等等...
因此,要检查其 managed-counterpart 是否存在,您可以简单地使用字典:
VB.Net/C#
Dim type As Type = unToManagedDict(UnmanagedType.AnsiBStr) 'VB.Net
Type type = unToManagedDict[UnmanagedType.AnsiBStr]; //C#
如果未找到非托管输入类型,这将引发异常错误,类似于您在
中所做的
Case Else
Throw New InvalidEnumArgumentException(argumentName:="type", invalidValue:=[type],
enumClass:=GetType(UnmanagedType))
这样,您就不需要使用新函数来处理您的映射。此外,您不需要每次都输入新的 Case
。
现在,除了样式之外,您对 "fill the emptiness" 的请求有点困难,因为并非所有 unmanaged
在 managed
中都有直接等效项。 (使用对比词 unmanaged
vs managed
本身就暗示了一些东西!)
但是,考虑到空箱子,我可能会这样做:
Case UnmanagedType.ByValArray -> Array (no best equivalent, but Array is the closest)
Case UnmanagedType.ByValTStr -> String (no best equivalent, but String could be used)
Case UnmanagedType.R4 -> Single
Case UnmanagedType.R8 -> Double
Case UnmanagedType.SafeArray -> Array (no best equivalent, but Array is the closest)
Case UnmanagedType.Struct -> some Structure (no equivalent, each struct is unique, best is to use Structure to wrap Struct)
你的可选问题是问反向操作是否安全。要反过来并完全等效,必须存在 one-to-one 关系。
即借用数学,如果x与f(x)的关系为bijection,则f(x)只能有f'(x)。由于当前从 UnmanagedType
到 Managed
的映射是 non-bijection,其中 UnmanagedType
的成员多于 Managed
-> 结论:反之则不安全.
Case UnmanagedType.Error
Return GetType(IntPtr)
没有。 IntPtr 表示一个虚拟地址,在 32 位平台上是 32 位的,在 64 位平台上是 64 位的。但是 UnmanagedType.Error
是固定大小的。它是一个 32 位有符号整数,主要用于表示操作的编码结果。这是用词不当,因为它 not always indicate an error.
Case UnmanagedType.IDispatch
Return GetType(IntPtr)
Case UnmanagedType.Interface
Return GetType(IntPtr)
Case UnmanagedType.IUnknown
Return GetType(IntPtr)
您可能应该使用 System.Object
。 UnmanagedType.Struct
.
也是如此
Case UnmanagedType.LPStr
Return GetType(StringBuilder)
嗯,您可以使用 StringBuilder 或 String,这取决于调用的函数。如果您正在进行一般转换,您可能应该使用 String。
Case UnmanagedType.R4
Case UnmanagedType.R8
分别对应System.Single
和System.Double
。
Case UnmanagedType.VariantBool
Return GetType(Boolean)
VariantBool
是 2 字节布尔类型,而 VB 布尔类型是 4 字节。您需要使用有符号或无符号的 2 字节整数类型。
Case UnmanagedType.VBByRefStr
Return GetType(String)
没有。 VBByRefStr
表示通过引用传递字符串。 That is, the address of the reference of the string. 因此,你应该 return Object
或 IntPtr
。该网页还表明 UnmanagedType.ByValTStr
是 String
.
UnmanagedType.ByValArray
、UnmanagedType.LPArray
和UnmanagedType.SafeArray
都对应System.Array
。我强烈建议阅读 this article to better understand these types. Also, if possible, you should create more specialized array types using this 技巧。
最后,我觉得你要么忘了要么省略了UnmanagedType.HString
和UnmanagedType.IInspectable
,分别对应String
和Object
我建议将 switch case 分组如下:数组类型、字符串类型、原始类型、其他指针类型和其他整数类型。
我正在尝试为 P/Invoking 执行此辅助函数,目的是帮助确定哪种托管类型最适合为 windows [=26= 的特定封送处理声明]定义。
我从这里获取信息:UnmanagedType Enumeration
在 C# 或 Vb.Net 中,我寻求帮助以填补空白案例并修复我当前的错误(如果有)。
(另外,作为一个可选的和定向的问题来回答或不回答:你认为写相反的东西可靠吗?,一种ManagedTypeToUnmanagedTypeEnum
功能。)
Public Shared Function UnmanagedTypeToManagedType(ByVal [type] As UnmanagedType) As Type
Select Case [type]
Case UnmanagedType.AnsiBStr
Return GetType(String)
Case UnmanagedType.AsAny
Return GetType(Object)
Case UnmanagedType.BStr
Return GetType(String)
Case UnmanagedType.Bool
Return GetType(Boolean)
Case UnmanagedType.ByValArray
Case UnmanagedType.ByValTStr
Case UnmanagedType.Currency
Return GetType(Decimal)
Case UnmanagedType.CustomMarshaler
Return GetType(Object)
Case UnmanagedType.Error
Return GetType(IntPtr)
Case UnmanagedType.FunctionPtr
Return GetType([Delegate])
Case UnmanagedType.I1
Return GetType(SByte)
Case UnmanagedType.I2
Return GetType(Short)
Case UnmanagedType.I4
Return GetType(Integer)
Case UnmanagedType.I8
Return GetType(Long)
Case UnmanagedType.IDispatch
Return GetType(IntPtr)
Case UnmanagedType.Interface
Return GetType(IntPtr)
Case UnmanagedType.IUnknown
Return GetType(IntPtr)
Case UnmanagedType.LPArray
Return GetType(IntPtr)
Case UnmanagedType.LPStr
Return GetType(StringBuilder)
Case UnmanagedType.LPStruct
Return GetType(IntPtr)
Case UnmanagedType.LPTStr
Return GetType(String)
Case UnmanagedType.LPWStr
Return GetType(String)
Case UnmanagedType.R4
Case UnmanagedType.R8
Case UnmanagedType.SafeArray
Case UnmanagedType.Struct
Case UnmanagedType.SysInt
Return GetType(IntPtr)
Case UnmanagedType.SysUInt
Return GetType(UIntPtr)
Case UnmanagedType.TBStr
Return GetType(String)
Case UnmanagedType.U1
Return GetType(Byte)
Case UnmanagedType.U2
Return GetType(UShort)
Case UnmanagedType.U4
Return GetType(UInteger)
Case UnmanagedType.U8
Return GetType(ULong)
Case UnmanagedType.VariantBool
Return GetType(Boolean)
Case UnmanagedType.VBByRefStr
Return GetType(String)
Case Else
Throw New InvalidEnumArgumentException(argumentName:="type", invalidValue:=[type],
enumClass:=GetType(UnmanagedType))
Return Nothing
End Select
End Function
对于这样的直接function-liketranslation/mapping(即每个唯一的X
恰好有一个Y
的值) ,我建议使用 Dictionary
而不是 switch
case
VB.Net/C#
Dim unToManagedDict As New Dictionary(Of UnmanagedType, Type) 'VB.Net
Dictionary<UnmanagedType, Type> unToManagedDict = new Dictionary<UnmanagedType, Type>(); //C#
然后在您的应用程序的第一次加载中列出您的 UnmanagedType
enum
,如下所示:
VB.Net/C#
unToManagedDict.Add(UnmanagedType.AnsiBStr, GetType(String)) 'VB.Net
unToManagedDict.Add(UnmanagedType.AsAny, GetType(Object)) 'VB.Net
'and so on... or,
unToManagedDict.Add(UnmanagedType.AnsiBStr, typeof(string)); //C# unToManagedDict.Add(UnmanagedType.AsAny, typeof(object)); //C# //等等...
因此,要检查其 managed-counterpart 是否存在,您可以简单地使用字典:
VB.Net/C#
Dim type As Type = unToManagedDict(UnmanagedType.AnsiBStr) 'VB.Net
Type type = unToManagedDict[UnmanagedType.AnsiBStr]; //C#
如果未找到非托管输入类型,这将引发异常错误,类似于您在
中所做的Case Else
Throw New InvalidEnumArgumentException(argumentName:="type", invalidValue:=[type],
enumClass:=GetType(UnmanagedType))
这样,您就不需要使用新函数来处理您的映射。此外,您不需要每次都输入新的 Case
。
现在,除了样式之外,您对 "fill the emptiness" 的请求有点困难,因为并非所有 unmanaged
在 managed
中都有直接等效项。 (使用对比词 unmanaged
vs managed
本身就暗示了一些东西!)
但是,考虑到空箱子,我可能会这样做:
Case UnmanagedType.ByValArray -> Array (no best equivalent, but Array is the closest)
Case UnmanagedType.ByValTStr -> String (no best equivalent, but String could be used)
Case UnmanagedType.R4 -> Single
Case UnmanagedType.R8 -> Double
Case UnmanagedType.SafeArray -> Array (no best equivalent, but Array is the closest)
Case UnmanagedType.Struct -> some Structure (no equivalent, each struct is unique, best is to use Structure to wrap Struct)
你的可选问题是问反向操作是否安全。要反过来并完全等效,必须存在 one-to-one 关系。
即借用数学,如果x与f(x)的关系为bijection,则f(x)只能有f'(x)。由于当前从 UnmanagedType
到 Managed
的映射是 non-bijection,其中 UnmanagedType
的成员多于 Managed
-> 结论:反之则不安全.
Case UnmanagedType.Error
Return GetType(IntPtr)
没有。 IntPtr 表示一个虚拟地址,在 32 位平台上是 32 位的,在 64 位平台上是 64 位的。但是 UnmanagedType.Error
是固定大小的。它是一个 32 位有符号整数,主要用于表示操作的编码结果。这是用词不当,因为它 not always indicate an error.
Case UnmanagedType.IDispatch
Return GetType(IntPtr)
Case UnmanagedType.Interface
Return GetType(IntPtr)
Case UnmanagedType.IUnknown
Return GetType(IntPtr)
您可能应该使用 System.Object
。 UnmanagedType.Struct
.
Case UnmanagedType.LPStr
Return GetType(StringBuilder)
嗯,您可以使用 StringBuilder 或 String,这取决于调用的函数。如果您正在进行一般转换,您可能应该使用 String。
Case UnmanagedType.R4
Case UnmanagedType.R8
分别对应System.Single
和System.Double
。
Case UnmanagedType.VariantBool
Return GetType(Boolean)
VariantBool
是 2 字节布尔类型,而 VB 布尔类型是 4 字节。您需要使用有符号或无符号的 2 字节整数类型。
Case UnmanagedType.VBByRefStr
Return GetType(String)
没有。 VBByRefStr
表示通过引用传递字符串。 That is, the address of the reference of the string. 因此,你应该 return Object
或 IntPtr
。该网页还表明 UnmanagedType.ByValTStr
是 String
.
UnmanagedType.ByValArray
、UnmanagedType.LPArray
和UnmanagedType.SafeArray
都对应System.Array
。我强烈建议阅读 this article to better understand these types. Also, if possible, you should create more specialized array types using this 技巧。
最后,我觉得你要么忘了要么省略了UnmanagedType.HString
和UnmanagedType.IInspectable
,分别对应String
和Object
我建议将 switch case 分组如下:数组类型、字符串类型、原始类型、其他指针类型和其他整数类型。