VB.NET 从 2.0 迁移到 .Net Standard 2.1 时库中断 - 请求的操作在 TryParse 上不可用
VB.NET library breaks on .Net Standard 2.1 when migrated from 2.0 - Requested operation is not avalaible on TryParse
有一个遗留的 Visual Basic class 库当前针对 .Net Standard 2.0:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.VisualBasic" Version="10.3.0" />
</ItemGroup>
</Project>
里面还有一个class
Public Class Class1
Public Shared Function TryGetInteger(ByVal value As Object) As Integer
Dim out As Integer
If Integer.TryParse(value, out) Then
Return out
End If
Return Integer.MinValue
End Function
Public Shared Function BooleanToInt(ByVal bValue As Object) As Integer
If (bValue = DBNull.Value) Then
Return 0
ElseIf bValue = True Then
Return 1
Else
Return 2
End If
End Function
End Class
此时一切正常。
但是将 <TargetFramework>netstandard2.0</TargetFramework>
更改为 2.1 会破坏构建并在 Class1.TryGetInteger
函数中出现以下错误:
Requested operation is not available because the runtime library function 'Microsoft.VisualBasic.CompilerServices.Conversions.ChangeType' is not defined
如何解决这个问题?
编辑: 请忽略以下想法:
第一个想法来自这个封闭的 github issue,建议将 <VBRuntime>Default</VBRuntime>
添加到项目文件中,但这会导致错误:
could not find library 'Microsoft.VisualBasic.dll'
但是它已经作为一个包被链接了...有什么想法吗?
编辑: 如评论所述,我对链接的 github 问题的看法有点误导,所以我想我回到了开头Requested operation is not available
错误。
当 Option Strict
设置为 Off
时,class 方法依赖于 VB 编译器实现的隐式类型转换。
重写代码最安全的方法是使用 de-compiler 并实现编译器使用的转换操作。这可能会涉及很多。
如果在调用 class 方法的代码中有一些合理性,那么可以像下面这样进行简单的重写以避免使用编译器的辅助转换方法。
Public Shared Function TryGetInteger(ByVal value As Object) As Integer
Dim out As Integer
If Integer.TryParse(value.ToString, out) Then
Return out
End If
Return Integer.MinValue
End Function
Public Shared Function BooleanToInt(ByVal bValue As Object) As Integer
If (bValue Is DBNull.Value) Then
Return 0
Else
If TypeOf bValue Is Boolean Then
Return If(DirectCast(bValue, Boolean), 1, 2)
Else
Throw New ArgumentException("type of bValue must be either DbNull or Boolean")
End If
End If
End Function
Integer.TryParse()
需要一个 String,但输入参数类型是 Object.
您可以这样解决问题:
Public Shared Function TryGetInteger(value As Object) As Integer
Dim out As Integer
If Integer.TryParse(value.ToString(), out) Then Return out
Return Nothing 'Same as Integer.MinValue in this context
End Function
额外的 ToString()
调用与旧框架隐式为您执行的操作相同。现在你知道了。
但我真的会这样做:
Public Shared Function TryGetInteger(value As String) As Integer
Dim out As Integer
If Integer.TryParse(value, out) Then Return out
Return Nothing
End Function
这可能会引发一整套新的编译器错误,但返回并在这些调用位置修复这些错误是有价值的。大多数错误都可以通过在调用函数时在值的末尾添加 .ToString()
来修复,而任何不能修复的错误几乎肯定是隐藏了错误。
与 BooleanToInt()
函数类似,我会使用 显式类型 ,并且可能会重载以获得更好的结果,如下所示:
Public Shared Function BooleanToInt(bValue As DBNull) As Integer
Return 0 'If this overload was selected, we know we want 0
End Function
Public Shared Function BooleanToInt(bValue As Boolean) As Integer
If bValue Then Return 1
Return 2
End Function
Public Shared Function BooleanToInt(bValue As Object) As Integer
Return 2
End Function
根据经验,任何需要直接使用 Object
类型的地方都会吸引错误。这是代码中的异味,需要避免。
有一个遗留的 Visual Basic class 库当前针对 .Net Standard 2.0:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.VisualBasic" Version="10.3.0" />
</ItemGroup>
</Project>
里面还有一个class
Public Class Class1
Public Shared Function TryGetInteger(ByVal value As Object) As Integer
Dim out As Integer
If Integer.TryParse(value, out) Then
Return out
End If
Return Integer.MinValue
End Function
Public Shared Function BooleanToInt(ByVal bValue As Object) As Integer
If (bValue = DBNull.Value) Then
Return 0
ElseIf bValue = True Then
Return 1
Else
Return 2
End If
End Function
End Class
此时一切正常。
但是将 <TargetFramework>netstandard2.0</TargetFramework>
更改为 2.1 会破坏构建并在 Class1.TryGetInteger
函数中出现以下错误:
Requested operation is not available because the runtime library function 'Microsoft.VisualBasic.CompilerServices.Conversions.ChangeType' is not defined
如何解决这个问题?
编辑: 请忽略以下想法:
第一个想法来自这个封闭的 github issue,建议将 <VBRuntime>Default</VBRuntime>
添加到项目文件中,但这会导致错误:
could not find library 'Microsoft.VisualBasic.dll'
但是它已经作为一个包被链接了...有什么想法吗?
编辑: 如评论所述,我对链接的 github 问题的看法有点误导,所以我想我回到了开头Requested operation is not available
错误。
当 Option Strict
设置为 Off
时,class 方法依赖于 VB 编译器实现的隐式类型转换。
重写代码最安全的方法是使用 de-compiler 并实现编译器使用的转换操作。这可能会涉及很多。
如果在调用 class 方法的代码中有一些合理性,那么可以像下面这样进行简单的重写以避免使用编译器的辅助转换方法。
Public Shared Function TryGetInteger(ByVal value As Object) As Integer
Dim out As Integer
If Integer.TryParse(value.ToString, out) Then
Return out
End If
Return Integer.MinValue
End Function
Public Shared Function BooleanToInt(ByVal bValue As Object) As Integer
If (bValue Is DBNull.Value) Then
Return 0
Else
If TypeOf bValue Is Boolean Then
Return If(DirectCast(bValue, Boolean), 1, 2)
Else
Throw New ArgumentException("type of bValue must be either DbNull or Boolean")
End If
End If
End Function
Integer.TryParse()
需要一个 String,但输入参数类型是 Object.
您可以这样解决问题:
Public Shared Function TryGetInteger(value As Object) As Integer
Dim out As Integer
If Integer.TryParse(value.ToString(), out) Then Return out
Return Nothing 'Same as Integer.MinValue in this context
End Function
额外的 ToString()
调用与旧框架隐式为您执行的操作相同。现在你知道了。
但我真的会这样做:
Public Shared Function TryGetInteger(value As String) As Integer
Dim out As Integer
If Integer.TryParse(value, out) Then Return out
Return Nothing
End Function
这可能会引发一整套新的编译器错误,但返回并在这些调用位置修复这些错误是有价值的。大多数错误都可以通过在调用函数时在值的末尾添加 .ToString()
来修复,而任何不能修复的错误几乎肯定是隐藏了错误。
与 BooleanToInt()
函数类似,我会使用 显式类型 ,并且可能会重载以获得更好的结果,如下所示:
Public Shared Function BooleanToInt(bValue As DBNull) As Integer
Return 0 'If this overload was selected, we know we want 0
End Function
Public Shared Function BooleanToInt(bValue As Boolean) As Integer
If bValue Then Return 1
Return 2
End Function
Public Shared Function BooleanToInt(bValue As Object) As Integer
Return 2
End Function
根据经验,任何需要直接使用 Object
类型的地方都会吸引错误。这是代码中的异味,需要避免。