Custom Rule Question

May 30, 2013 at 12:14 PM
Edited May 30, 2013 at 12:18 PM

I am planning to use this engine in an application that I am currently developing but I am trying to do the following.

Assuming I have a table in the database called "Companies" with 2 columns "Code" and "Name". The "Code" is the primary key. What I need is, in addition to the normal rules I setup for the "Company" class, I need to declare a custom rule for the "Name" property to make sure that the value is always unique.

Well I managed to develop it using the example you posted in the documentation, and following is the code in VB.NET
Friend Class CompanyDuplicationNameRule
        Implements IRule(Of String)

        Private _Code As String = String.Empty

        Friend Sub New(ByVal Code As String)
            _Code = Code
        End Sub

        Public ReadOnly Property RuleKind As String Implements IRule.RuleKind
                Return "Duplicate Value Rule"
            End Get
        End Property

        Public Function Validate(value As String) As ValidationResult Implements IRule(Of String).Validate
            Using _DB As New ConsolidationDBContext
                Dim _Company As Company = (From _C As Company In _DB.Companies Where _C.Name = value AndAlso _C.Code <> _Code Select _C).SingleOrDefault()
                If (_Company Is Nothing) Then Return ValidationResult.Success
                Return ValidationResult.Fail
            End Using
        End Function
    End Class
Now, in the setup process of the rules, I added all the required rules in addition to the rule I mentioned above, but my question is, how can I tell the engine that when you need to fire the validate method, pass the code to the rule as I need it in my validation logic. Here is the code of the rules' setup in VB.NET
_Engine.[For](Of Company)().Setup(Function(Record As Company) Record.Code).MustNotBeNullOrEmpty().WithMessage(" - The Company Code is required.").EndSetup()
            _Engine.[For](Of Company)().Setup(Function(Record As Company) Record.Code.Length).MustBeLessThanOrEqualTo(10).WithMessage(" - The Length of the Company Code must be less or equal to 10 characters.").EndSetup()
            _Engine.[For](Of Company)().Setup(Function(Record As Company) Record.Name).MustPassRule(New CompanyDuplicationNameRule(<What to pass here as the code>))
Your prompt response is highly appreciated.

May 30, 2013 at 10:53 PM
Hi Michael,

You don't have to do anything...
When calling engine.Validate(myCompany), all the rules defined for the Company will be executed in the order they were defined...

There is nothing in your CompanyDuplicationNameRule constructor, so plain "new CompanyDuplicationNameRule()" is enough.

The Validate method of your rule will be executed with the Name of the Company. The RuleEngine's job is to fetch the Name (defined as a lambda) from a Company object and pass that on to the CompanyDuplicationNameRule.

Hope this answers your question


May 31, 2013 at 7:01 PM
Thanks Arnaud for your prompt response. I am not sure if I am following you here, but in my case, upon validating the "Company" object using the "Validate" method, I need to execute a custom rule to validate the "Name" property. This rule makes sure that the name is unique. So it needs to hold the required code which communicates with the database. This is what I wrote in my example. The point is, I need the ID/Code of the object to be validated at the time of building the rule, to make sure that the name is really unique.

In the explanation above, I don't see how I can achieve this. Can you please elaborate more about this.

Many thanks,
May 31, 2013 at 10:00 PM
Edited May 31, 2013 at 10:01 PM
I see,

VB is hard to read, sorry. So 'Name' is not enough for your rule, you need to your rule to receive a whole 'Company' object so you can use it's 'Code' as part of the validation as well...

You need a IRule(Of Company) instead of an IRule(Of String).
public class CompanyDuplicationNameRule : IRule<Company> {...}
When defining your rules on the Engine
    For<Company>().MustPassRule(new CompanyDuplicationNameRule());
(No need a 'Setup' to get any property from the Company object since you want to validate the Company object itself)