Vb.net 由变量分隔符分隔的对象链的类设计/模式
我正在VB.NET中创建一个生成SQL字符串的库。然而,生成Vb.net 由变量分隔符分隔的对象链的类设计/模式,vb.net,Vb.net,我正在VB.NET中创建一个生成SQL字符串的库。然而,生成WHERE子句(以及类似的结构)给了我一个问题。我发现最简单的where子句结构本质上是 expression1 [AND expression2 [AND expressionN]] 这很容易在代码中用表达式对象列表表示-然后程序只需遍历每个对象,调用其重写的ToString()方法,并每次追加和(最后一个除外)。简单。当考虑到或时,就会出现复杂情况:where子句的结构变得复杂 expression1 [[AND|OR] expr
WHERE
子句(以及类似的结构)给了我一个问题。我发现最简单的where子句结构本质上是
expression1 [AND expression2 [AND expressionN]]
这很容易在代码中用表达式
对象列表表示-然后程序只需遍历每个对象,调用其重写的ToString()
方法,并每次追加和
(最后一个除外)。简单。当考虑到或时,就会出现复杂情况:where子句的结构变得复杂
expression1 [[AND|OR] expression2 [[AND|OR] expressionN]]
我现在需要既能保存所有表达式,又能跟踪每个表达式是否被和或或分隔开来,这是的基本集合(expr1,andro1,expr2,andro2,…exprN,andron)
我还考虑过结构也可以嵌套,例如:
(expression1 [[AND|OR] expression2]) [AND|OR] (expression3 [[AND|OR] expression4])
其中,每个圆括号中的一半本身就是一个表达式。因此,我认为解决方案是进一步扩展Expression
类,这样一个表达式可以是一个表达式链:我有一个新类Expression fromChainofExpressions
:
Public Class ExpressionFromChainOfExpressions
Inherits Expression
Private ExprChain As List(Of Expression)
Public Sub AddExpression(Expr As Expression)
If ExprChain Is Nothing Then ExprChain = New List(Of Expression)
ExprChain.Add(Expression)
End Sub
Public Overrides Function ToString() As String
Dim outStr As String = "("
For i = 0 To ExprChain.Count - 1
outStr &= Expr.ToString()
If i < ExprChain.Count - 1
'ToDo: Determine [AND|OR] and append
'OLD: outStr &= " AND "
End If
Next
Return outStr & ")"
End Function
End Class
主要方法:
Public Module Module1
Dim myExpr1 = New ExpressionFromString("A = B")
Dim myExpr2 = New ExpressionFromString("C > 100")
dIM myExpr3 = New ExpressionFromString("D Is Null")
Dim myNestedChain = New ExpressionFromChainOfExpressions()
myExprChain.Add(myExpr1)
myExprChain.Add(myExpr2)
Console.WriteLine("WHERE " & myNestedChain.ToString() )
Dim myOuterChain = New ExpressionFromChainOfExpressions()
myOuterChain.Add(myNestedChain)
myOuterChain.Add(myExpr3)
Console.WriteLine("WHERE " & myOuterChain.ToString() )
End Module
产出:
WHERE (A = B AND C > 100)
WHERE ((A = B AND C > 100) AND D Is Null)
下面是如何面对您的问题的建议:
Public Class ExpressionFromChainOfExpressions
Inherits Expression
Private ExprChain As List(Of Expression)
Private ExprConn As List(Of Connector)
Public Enum Connector
AndConn
OrConn
End Enum
Public Sub AddExpression(Expr As Expression) 'Might have to be changed to account for connectors
If ExprChain Is Nothing Then ExprChain = New List(Of Expression)
ExprChain.Add(Expr)
End Sub
Public Overrides Function ToString() As String
Dim outStr As String = "("
For i = 0 To ExprChain.Count - 1
outStr &= ExprChain(i).ToString()
If i < ExprChain.Count - 1 Then
outStr &= 'will account for the given connector (as stored in ExprConn)
End If
Next
Return outStr & ")"
End Function
End Class
公共类表达式fromChainofExpressions
继承表达式
私有扩展为列表(表达式)
专用ExprConn As列表(连接器)
公共枚举连接器
安德康
奥康
结束枚举
可能必须更改Public Sub AddExpression(Expr As Expression)“”以考虑连接器
如果ExprChain为Nothing,则ExprChain=新列表(表达式)
ExprChain.Add(Expr)
端接头
Public将函数ToString()重写为字符串
Dim OUNTR As String=“(”
对于i=0的表达式,计数为-1
outtr&=ExprChain(i).ToString()
如果我
在定义输入表达式时,定义输入连接器
(a公共枚举
,包括您想要的所有备选方案(“And”和“Or”);请记住,“And”和“Or”不能使用,因此必须使用等效名称)。通过遵循当前版本的类
中的想法,您可能会包含一个AddConnector
函数,尽管这会使一切变得太混乱(每次调用两个,表达式与连接器的关联困难等)。我建议您更改AddExpression,使其至少接受两个参数:Expression和Connector(参考前面的输入表达式或下一个输入表达式);通过这种方式,您将能够并行地填充这两个列表(ExprChain
和ExprConn
),并将它们完美地协调以用于ToString()
我自己对varocabas解决方案的修改,通过IsNested
布尔值,可以更好地控制嵌套,并且不依赖于两个集合的排序:
Public Class ExpressionFromChainOfExpressions
Inherits Expression
Private ExprChain As List(Of Expression)
'Alternatively use an Enum as per varocarbas's solution
'for better consistency control
Private ChainWord As String
'If true, wraps ( ) around ToString()'s output
Private IsNested As Boolean
Public Sub New(ByVal ChainWord As String, ByVal IsNested As Boolean)
Me.ChainWord = ChainWord
Me.IsNested = IsNested
End Sub
Public Sub AddExpression(ByVal Expr As Expression)
If ExprChain Is Nothing Then ExprChain = New List(Of Expression)
ExprChain.Add(Expr)
End Sub
Public Overrides Function ToString() As String
Dim outStr As String = ""
If IsNested Then outStr = "("
For i = 0 To ExprChain.Count - 1
outStr &= ExprChain(i).ToString()
If i < ExprChain.Count - 1 Then
outStr &= String.Format(" {0} ", ChainWord)
End If
Next
If IsNested Then outStr = ")"
Return outStr
End Function
End Class
我不是100%确定你到底想要完成什么;但您知道和/或(以及像AndAlso这样的替代方案)是ExpressionType枚举()的一部分,不是吗?是的,谢谢,我知道。为了澄清,这里的和
/或
只是一个输出字符串,需要存储在某个地方并用于链接表达式(程序本身并不使用它们来运行条件检查)。对于所有的程序来说,它可能是香蕉
/华夫饼
——关键是我需要某种方法来定义一个链,其中链中的每个链接都由和或或分开(或香蕉
或华夫饼
):)你能用类的输入写一个实际的例子吗(ExpressionFromChainOfExpressions变量为…)和ToString重写函数的预期输出(当执行.ToString()时,我想得到…)?这肯定有助于明确您想要的确切内容。添加了示例代码(这里没有包括表达式的其他几个具体实现,表达式还有一些其他的活动部分,但它们并不相关,因此为了简洁起见省略)谢谢。我认为你的代码有一些错误,但至少现在给出了一个足够清晰的画面。请简要回复。我回到这里是为了发布我自己在咖啡休息脑波中找到的答案(我发现咖啡休息有时是我一天中最有效率的部分!)…它几乎与此解决方案一字不差。我的使用字符串而不是枚举,因此我确实可以使用a=b华夫饼干c>100
,尽管我仍在讨论使用哪个。我的还有一个IsNested
布尔成员,它决定是否包装()
围绕输出,这允许更好地控制更复杂的嵌套。在任何情况下,完美的答案,谢谢!@kai欢迎您。我建议您使用枚举。它比看起来有用得多;主要是当您必须大量使用给定类时。
Public Class ExpressionFromChainOfExpressions
Inherits Expression
Private ExprChain As List(Of Expression)
'Alternatively use an Enum as per varocarbas's solution
'for better consistency control
Private ChainWord As String
'If true, wraps ( ) around ToString()'s output
Private IsNested As Boolean
Public Sub New(ByVal ChainWord As String, ByVal IsNested As Boolean)
Me.ChainWord = ChainWord
Me.IsNested = IsNested
End Sub
Public Sub AddExpression(ByVal Expr As Expression)
If ExprChain Is Nothing Then ExprChain = New List(Of Expression)
ExprChain.Add(Expr)
End Sub
Public Overrides Function ToString() As String
Dim outStr As String = ""
If IsNested Then outStr = "("
For i = 0 To ExprChain.Count - 1
outStr &= ExprChain(i).ToString()
If i < ExprChain.Count - 1 Then
outStr &= String.Format(" {0} ", ChainWord)
End If
Next
If IsNested Then outStr = ")"
Return outStr
End Function
End Class
expr1 AND expr2 OR (exp3 AND (expr4 OR expr5 AND expr6 AND expr7))