Imports IdeaBlade.Persistence Imports DevExpress.Data.Filtering Namespace Filtering ''' ''' Convert a filter created by DevExpress FilterControl into a DevForce EntityQuery. ''' ''' ''' Dim visitor As New CriteriaVisitor(Of Employee) ''' mFilterControl.FilterCriteria.Accept(visitor) ''' Debug.WriteLine(visitor.Query.ToString) ''' ''' ''' Entity type for wich we want to generate EntityQuery ''' RF 2009-06-16 Public Class CriteriaVisitor(Of T As Entity) Implements DevExpress.Data.Filtering.ICriteriaVisitor ''' ''' Generated EntityQuery object. ''' ''' Private mQuery As New EntityQuery(GetType(T)) ''' ''' Generated EntityQuery object ''' ''' ''' Generated EntityQuery object ''' Public ReadOnly Property Query() As EntityQuery Get Return mQuery End Get End Property Private Sub VisitRight(ByVal theOperator As CriteriaOperator) If TypeOf theOperator Is GroupOperator Then Visit(CType(theOperator, GroupOperator)) ElseIf TypeOf theOperator Is BinaryOperator Then Visit(CType(theOperator, BinaryOperator)) ElseIf TypeOf theOperator Is InOperator Then Visit(CType(theOperator, InOperator)) ElseIf TypeOf theOperator Is OperandValue Then Visit(CType(theOperator, OperandValue)) ElseIf TypeOf theOperator Is BetweenOperator Then Visit(CType(theOperator, BetweenOperator)) ElseIf TypeOf theOperator Is UnaryOperator Then Visit(CType(theOperator, UnaryOperator)) 'ElseIf TypeOf theOperator Is FunctionOperator Then ' Visit(CType(theOperator, FunctionOperator)) Else ThrowEx(String.Format("CriteriaOperator type '{0}' not implemented", theOperator.GetType.ToString)) End If End Sub Public Function Visit(ByVal theOperator As BetweenOperator) As Object Implements ICriteriaVisitor.Visit If TypeOf theOperator.BeginExpression Is DevExpress.Data.Filtering.OperandValue _ AndAlso TypeOf theOperator.EndExpression Is DevExpress.Data.Filtering.OperandValue Then Dim oLeft As OperandValue = CType(theOperator.BeginExpression, OperandValue) Dim oRight As OperandValue = CType(theOperator.EndExpression, OperandValue) Dim sPropertyName As String = CType(theOperator.TestExpression, OperandProperty).PropertyName Dim oColumn As EntityColumn = GetEntityColumn(sPropertyName) If oColumn Is Nothing Then ThrowEx(String.Format("No EntityColumn correspond to property '{0}' in System.Type '{1}'", sPropertyName, GetType(T).Name)) Else mQuery.AddClause(New EntityQueryClause(oColumn, EntityQueryOp.Between, oLeft.Value, oRight.Value)) End If End If Return Nothing End Function Public Function Visit(ByVal theOperator As BinaryOperator) As Object Implements ICriteriaVisitor.Visit Dim oOperator As EntityQueryOp = Nothing Select Case theOperator.OperatorType Case BinaryOperatorType.Equal oOperator = EntityQueryOp.EQ Case BinaryOperatorType.NotEqual oOperator = EntityQueryOp.NE Case BinaryOperatorType.Greater oOperator = EntityQueryOp.GT Case BinaryOperatorType.GreaterOrEqual oOperator = EntityQueryOp.GE Case BinaryOperatorType.Less oOperator = EntityQueryOp.LT Case BinaryOperatorType.LessOrEqual oOperator = EntityQueryOp.LE Case BinaryOperatorType.Like oOperator = EntityQueryOp.Like Case Else ThrowEx(String.Format("BinaryOperator '{0}' not implemented", theOperator.OperatorType.ToString)) End Select If TypeOf theOperator.LeftOperand Is OperandProperty Then If oOperator IsNot Nothing Then Dim sPropertyName As String = CType(theOperator.LeftOperand, OperandProperty).PropertyName mQuery.AddClause(New EntityQueryClause(sPropertyName, oOperator, theOperator.RightOperand.ToString.Trim("'"c))) Else ThrowEx(String.Format("OperatorType '{0}' not implemented", theOperator.OperatorType.ToString)) End If Else ThrowEx("LeftOperand type different of OperandProperty is not implemented") End If Return Nothing End Function Public Function Visit(ByVal theOperator As GroupOperator) As Object Implements ICriteriaVisitor.Visit For Each bin As CriteriaOperator In theOperator.Operands VisitRight(bin) Next For i As Integer = 1 To theOperator.Operands.Count - 1 If theOperator.OperatorType = GroupOperatorType.And Then mQuery.AddOperator(EntityBooleanOp.And) ElseIf theOperator.OperatorType = GroupOperatorType.Or Then mQuery.AddOperator(EntityBooleanOp.Or) End If Next Return Nothing End Function Public Function Visit(ByVal theOperator As InOperator) As Object Implements ICriteriaVisitor.Visit Dim oList As New List(Of Object) For Each bin As CriteriaOperator In theOperator.Operands If TypeOf bin Is DevExpress.Data.Filtering.OperandValue Then oList.Add(CType(bin, OperandValue).Value) End If Next If oList.Count > 0 Then Dim sPropertyName As String = CType(theOperator.LeftOperand, OperandProperty).PropertyName mQuery.AddClause(New EntityQueryClause(sPropertyName, EntityQueryOp.In, oList.ToArray)) End If Return Nothing End Function Public Function Visit(ByVal theOperator As UnaryOperator) As Object Implements ICriteriaVisitor.Visit If theOperator.OperatorType = UnaryOperatorType.Not Then VisitRight(theOperator.Operand) mQuery.AddOperator(EntityBooleanOp.Not) Else If theOperator.OperatorType = UnaryOperatorType.IsNull Then If TypeOf theOperator.Operand Is OperandProperty Then mQuery.AddClause(New EntityQueryClause(CType(theOperator.Operand, OperandProperty).PropertyName, EntityQueryOp.IsNull, Nothing)) Else ThrowEx(String.Format("Operator.Operand type different of OperandProperty ({0}) is not implemented", theOperator.Operand.GetType.ToString)) End If Else ThrowEx(String.Format("OperatorType '{0}' not implemented", theOperator.OperatorType.ToString)) End If End If Return Nothing End Function #Region " To be completed " Public Function Visit(ByVal theOperator As FunctionOperator) As Object Implements ICriteriaVisitor.Visit ThrowEx("CriteriaVisitor.Visit(ByVal theOperator As FunctionOperator) not implemented") Return Nothing End Function Public Function Visit(ByVal theOperand As OperandValue) As Object Implements ICriteriaVisitor.Visit ThrowEx("CriteriaVisitor.Visit(ByVal theOperand As OperandValue) not implemented") Return Nothing End Function Private Sub ThrowEx(Optional ByVal msg As String = "") If msg = "" Then Throw New NotImplementedException("QueryCriteria specific method not implemented.") Else Throw New NotImplementedException(msg) End If End Sub #End Region ''' ''' Return the Entitycolumn based on the provided property name. ''' ''' Property name for wich we want the EntityColumn ''' ''' Private Function GetEntityColumn(ByVal PropertyName As String) As EntityColumn If Not PropertyName.EndsWith("EntityColumn") Then PropertyName &= "EntityColumn" End If Dim oType As System.Type = GetType(T).BaseType If oType.GetField(PropertyName) IsNot Nothing Then Dim oValue As Object = oType.GetField(PropertyName).GetValue(Nothing) If TypeOf oValue Is EntityColumn Then Return CType(oValue, EntityColumn) Else Return Nothing End If Else Return Nothing End If End Function End Class End Namespace