我正在尝试关注this series of articles。我在第2和第3部分之间,但我遇到了一些问题。
我正在VB.Net中编写代码,这引起了一些怪癖。
具体来说,在访问表达式树时,字符串比较无法按预期工作。
QueryProvider中的此方法(Part 2)
Protected Overrides Function VisitMethodCall(m As MethodCallExpression) As Expression
If m.Method.DeclaringType = GetType(Queryable) AndAlso m.Method.Name = "Where" Then
sb.Append("SELECT * FROM (")
Me.Visit(m.Arguments(0))
sb.Append(") AS T WHERE ")
Dim lambda As LambdaExpression = DirectCast(StripQuotes(m.Arguments(1)), LambdaExpression)
Me.Visit(lambda.Body)
Return m
End If
Throw New NotSupportedException(String.Format("The method '{0}' is not supported", m.Method.Name))
End Function
为字符串比较抛出NotImplementedException
m.Method.DeclaringType
类型为Microsoft.VisualBasic.CompilerServices.Operators
,m.Method.Name
为CompareString
。看起来VB的字符串相等处理方式略有不同,并且没有以正确的方式获取。
我正在使用Query.Where(function(x) x.Content_Type <> "")
进行测试。
具体来说,如果我调用VisitBinary(b As BinaryExpression)
(同时Part 2)的调用,b
为{(CompareString(x.Content_Type, "", False) != 0)}
然后尝试访问b.Left
(CompareString(x.Content_Type, "", False)
),这是VisitMethodCall
中的漏洞。
如果我只是将VisitMethodCall中的If扩展为
If (
m.Method.DeclaringType = GetType(Queryable) AndAlso
m.Method.Name = "Where"
) Or (
m.Method.DeclaringType = GetType(Microsoft.VisualBasic.CompilerServices.Operators) AndAlso
m.Method.Name = "CompareString") Then
在尝试将StripQuotes(m.Arguments(1))
转换为LambdaExpression
时会抛出InvalidCastException(表示它是ConstantExpression
)
我需要做什么才能正确处理VB中的字符串比较?
答案 0 :(得分:2)
使用以下课程:
Imports System.Linq.Expressions
Public Class VbCompareReplacer
Inherits ExpressionVisitor
Public Overrides Function Visit(node As Expression) As Expression
If Not TypeOf node Is BinaryExpression Then Return MyBase.Visit(node)
Dim binaryExpression = DirectCast(node, BinaryExpression)
If Not TypeOf binaryExpression.Left Is MethodCallExpression Then Return MyBase.Visit(node)
Dim method = DirectCast(binaryExpression.Left, MethodCallExpression)
If Not (method.Method.DeclaringType = GetType(Microsoft.VisualBasic.CompilerServices.Operators) AndAlso
method.Method.Name = "CompareString") Then Return MyBase.Visit(node)
Dim left = method.Arguments(0)
Dim right = method.Arguments(1)
Return If(binaryExpression.NodeType = ExpressionType.Equal,
Expression.Equal(left, right),
Expression.NotEqual(left, right))
End Function
End Class
现在,如果您有来自vb编译器的表达式,例如
Dim expressionFromVb As Expression(Of Func(Of String, Boolean)) = Function(x) x = "b"
具有结构{(CompareString(x,&#34; b&#34;,False)== 0)}使用
Dim newExpression = New VbCompareReplacer().Visit(expressionFromVb)
而不是expressionFromVb
,其结构为{x =&gt; (x ==&#34; b&#34;)}。所有混乱的vb比较都被预期的(in-)相等比较所取代。如果将newExpression
放入为c#编写的linq提供程序中,它现在应该可以正常工作。