2016-01-01 8 views
-2

Я пытаюсь выполнить эту вспомогательную функцию для P/Invoking, целью которой является определение того, какой должен быть наиболее подходящий управляемый тип для объявления определенных маршалингов определения API Windows ,Перевести значения перечисления UnmanagedType на их эквиваленты управляемого типа

Я взял информацию здесь: 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 
+0

Этот вопрос основан на ошибочной предпосылке. Семантика параметра не задается по типу. Между управляемыми и неуправляемыми типами нет однозначного сопоставления. Функции, которые вы пытаетесь построить, бесполезны. –

+1

@DavidHeffernan OP знает, что между управляемыми и неуправляемыми типами нет однозначного сопоставления, потому что он попросил ** наиболее подходящий тип **. Вопрос в том, что из сопоставления «много-во» между управляемыми и неуправляемыми типами построение типичного сопоставления «один-к-одному». Поскольку ОП не уточнил, почему он хочет такую ​​функцию или для чего ее будут использовать, трудно понять, является ли она совершенно бесполезной или нет. –

+0

@Hadi Пожалуйста, определите «наиболее подходящий тип». Я поражен тем, что вам удалось это сделать, не зная о применении этой карты. –

ответ

3
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.

Ну, вы можете использовать StringBuilder или String, это зависит от вызываемой функции. Если вы делаете общее преобразование, вы, вероятно, должны использовать String.

Case UnmanagedType.R4 

Case UnmanagedType.R8 

Они соответствуют System.Single и System.Double соответственно.

Case UnmanagedType.VariantBool 
    Return GetType(Boolean) 

VariantBool является 2-байтовое Логический тип, но тип В. Б. Логическое составляет 4 байта. вам нужно использовать подписанный или неподписанный 2-байтовый интегральный тип.

Case UnmanagedType.VBByRefStr 
    Return GetType(String) 

No. VBByRefStr означает передачи строки по ссылке. That is, the address of the reference of the string. Следовательно, вы должны вернуть Object или IntPtr. Эта веб-страница также сообщает, что UnmanagedType.ByValTStr является String.

UnmanagedType.ByValArray, UnmanagedType.LPArray и UnmanagedType.SafeArray все соответствуют System.Array. Я настоятельно рекомендую прочитать статью this, чтобы лучше понять эти типы. Кроме того, если возможно, вам следует создать более специализированные типы массивов с использованием метода this.

Наконец, я думаю, вы или забыли или опущены UnmanagedType.HString и UnmanagedType.IInspectable, которые соответствуют String и Object соответственно.

Я предлагаю группировать корпуса коммутаторов следующим образом: типы массивов, типы строк, примитивные типы, другие типы указателей и другие целочисленные типы.

2

Для такого прямого FUNCTION- как перевод/отображение (то есть, каждый уникальный X имеет ровно одно значение Y), я бы рекомендовал использовать Dictionary вместо switch случае

VB.Net/C#

Dim unToManagedDict As New Dictionary(Of UnmanagedType, Type) 'VB.Net 

Dictionary<UnmanagedType, Type> unToManagedDict = new Dictionary<UnmanagedType, Type>(); //C# 

Затем перечислите ваши UnmanagedTypeenum в первой загрузке вашего приложения, как это:

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 (строка)); // C# unToManagedDict.Add (UnmanagedType.AsAny, typeof (object)); // C# // и так далее ...

Так, чтобы проверить его удалось-партнерское существование вы могли бы просто использовать словарь:

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 каждый раз.

Теперь, помимо стиля, ваш запрос «заполнить пустоту» несколько сложнее, поскольку не все 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) 

Ваш факультативный вопрос спрашивает, если это безопасно сделать наоборот. Чтобы сделать обратное и быть абсолютно эквивалентным, должно быть взаимно однозначное отношение.

То есть, заимствуя из математики, f (x) может иметь только f '(x), если соотношение между x и f (x) равно bijection. Поскольку текущее отображение от UnmanagedType до Managed является не биекционным, где член UnmanagedType больше, чем Managed -> Вывод: обратный не так безопасен.

 Смежные вопросы

  • Нет связанных вопросов^_^