|
Public MustInherit Class Specification(Of T)
#Region "Declarations"
Private AndSpec As Specification(Of T)
Private OrSpec As Specification(Of T)
Private IsNegated As Boolean
#End Region
#Region "Must Override"
Protected MustOverride Function SpecificationRule(ByVal obj As T) As Boolean
#End Region
#Region "Public Methods"
Public Function IsSatisfiedBy(ByVal obj As T) As Boolean
' Test this Spec
Dim blnIsSatisfied As Boolean = SpecificationRule(obj)
' Test the AND Branch of the Tree
If Not AndSpec Is Nothing Then
blnIsSatisfied = blnIsSatisfied And AndSpec.IsSatisfiedBy(obj)
End If
' Test the OR Branch of the Tree
If Not OrSpec Is Nothing Then
blnIsSatisfied = blnIsSatisfied Or OrSpec.IsSatisfiedBy(obj)
End If
' Apply the Not Flag
blnIsSatisfied = blnIsSatisfied Xor IsNegated
Return blnIsSatisfied
End Function
#End Region
#Region "Operators"
Protected Shared Function AndOperator(ByVal a As Specification(Of T), ByVal b As Specification(Of T)) As Specification(Of T)
Dim newSpec As Specification(Of T) = a.Copy
newSpec.SetAnd(b.Copy)
Return newSpec
End Function
Protected Shared Function OrOperator(ByVal a As Specification(Of T), ByVal b As Specification(Of T)) As Specification(Of T)
Dim newSpec As Specification(Of T) = a.Copy
newSpec.SetOr(b.Copy)
Return newSpec
End Function
Protected Shared Function NotOperator(ByVal a As Specification(Of T)) As Specification(Of T)
Dim newSpec As Specification(Of T) = a.Copy
newSpec.SetNot(Not a.IsNegated)
Return newSpec
End Function
#End Region
#Region "Private"
Private Sub SetAnd(ByVal spec As Specification(Of T))
' If setting to nothing, set it directly
If spec Is Nothing Then
AndSpec = spec
Exit Sub
End If
' If setting to an actual spec, then attach to the end of any existing spec
If AndSpec Is Nothing Then
' No existing spec, so set directly
AndSpec = spec
Else
' Recursively call SetAnd until we get to the end of the chain of specs
AndSpec.SetAnd(spec)
End If
End Sub
Private Sub SetOr(ByVal spec As Specification(Of T))
' If setting to nothing, set it directly
If spec Is Nothing Then
OrSpec = spec
Exit Sub
End If
' If setting to an actual spec, then attach to the end of any existing spec
If OrSpec Is Nothing Then
' No existing spec, so set directly
OrSpec = spec
Else
' Recursively call SetOr until we get to the end of the chain of specs
OrSpec.SetOr(spec)
End If
End Sub
Private Sub SetNot(ByVal value As Boolean)
IsNegated = value
End Sub
Private Function Copy() As Specification(Of T)
' Copy this spec
Dim newSpec As Specification(Of T)
newSpec = CType(Me.MemberwiseClone, Specification(Of T))
' Clear the andSpec and orSpec so they can be pointed at copies of the existing andSpec and orSpec
' After the MemberwiseClone the newSpec points to the same subSpecs
newSpec.SetAnd(Nothing)
newSpec.SetOr(Nothing)
If Not AndSpec Is Nothing Then
newSpec.SetAnd(AndSpec.Copy)
End If
If Not OrSpec Is Nothing Then
newSpec.SetOr(OrSpec.Copy)
End If
Return newSpec
End Function
#End Region
End Class
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.