![]() |
Development Lifecycle »
Design and Architecture »
Design Patterns
Intermediate
License: The Code Project Open License (CPOL)
A Generic Specification in VB.NETBy daltonrPart three of a four part series of articles on the Specification Design Pattern. |
VB 8.0, VB 9.0.NET 2.0, .NET 3.0, .NET 3.5, Architect, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
This is the third in a series of four articles discussing the Specification Design Pattern and how to implement it using VB.NET.
The Specification Design Pattern was created by Eric Evans. He provides a description of the pattern in his book, 'Domain Driven Design'. This series of articles shows how to implement the pattern using VB.NET.
The IsSatisfiedBy function only needs to be written once in the base Specification class. The much simpler SpecificationRule which is coded in our concrete specifications only has to concern itself with the very specific task of examining the candidate object that is passed to it.
The logic for combining specifications using Operators is implemented in three functions in the base Specification. The concrete specifications will call these methods from overloaded operator functions. This will be seen in part four of this series.
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
These operator functions rely on four private functions: SetAnd, SetOr, SetNot, and Copy. These functions implement the real logic for creating complex combinations of specifications.
In simple terms, each specification has two branches from itself, each capable of pointing to another specification. When the specification is evaluated in the IsSatisfiedBy function seen above, that function takes care of evaluating any specifications it points to. This continues recursively until all specifications are evaluated.
The SetAnd and SetOr methods are passed a specification that is to be joined to an existing specification. The SetAnd method attaches it to the AND branch, and the SetOr method attaches it to the OR branch. Obviously, the specification being added could itself be the root of a tree containing multiple specifications.
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 the existing chain of specs
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
The NOT operator is a simple boolean flag. If it is set, then the result of the specification is negated.
Private Sub SetNot(ByVal value As Boolean)
IsNegated = value
End Sub
We also need a copy function that can copy a specification or a tree of specifications. This is used by the AndOperator, OrOperator, and NotOperator functions.
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
In the concluding part of this series, we'll build a new version of the ContainerSpecification class which inherits from the Specification class. We'll then declare a number of ContainerSpecifications and combine them.
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 5 Apr 2009 Editor: Smitha Vijayan |
Copyright 2009 by daltonr Everything else Copyright © CodeProject, 1999-2009 Web16 | Advertise on the Code Project |