Writing a Custom NHibernate Class Validator

I've been asked a few times if it's possible to use NHibernate Validator to create a custom validator at the class level, in addition to custom property validators.  The short answer is yes.  (But it would make a rather uninteresting post if I stopped here.)  The documentation at http://nhforge.org/wikis/validator/nhibernate-validator-1-0-0-documentation.aspx gives a hint at how to do it, but doesn't go into a lot of detail. So what follows is an example of creating a class validator for use with NHibernate Validator.

Let's assume you have a class with a requirement that one property be true or another one be true, but not both; i.e., XOR. The end goal would be to use a validator on your class as follows:

[EnforceXorOfProperty1AndProperty2] 
public class MyObject
{ 
    public bool MyProperty1 { get; set; } 
    public bool MyProperty2 { get; set; } 
}

To implement this validator, you need to create a validation attribute class along with the validation class to carry out the validation logic. To demonstrate:

[ValidatorClass(
    typeof(EnforceXorOfProperty1AndProperty2Validator)), 
    AttributeUsage(AttributeTargets.Class)]
private class EnforceXorOfProperty1AndProperty2Attribute 
    : Attribute, IRuleArgs 
{ 
    /// 
    /// Since this is a very specialized validator
    /// we'll make the message read-only
    /// 
    public string Message { 
        get { 
            return "Either property 1 or property 2 " +
                "needs to be checked, but not both"; 
        } 
        set { } 
    } 
} 

private class EnforceXorOfProperty1AndProperty2Validator 
    : IInitializableValidator 
{ 
    public void Initialize(EnforceXorOfProperty1AndProperty2Attribute attribute) { } 

    public bool IsValid(object value) { 
        MyObject myObjectToValidate = value as MyObject; 
        // DbC to make sure it's being used on a MyObject
        Check.Require(myObjectToValidate != null, 
            "This validator may only be used on a MyObject");

        return myObjectToValidate.MyProperty1 
            ^ myObjectToValidate.MyProperty2; 
    } 
}

And that's all there is to it. I typically keep my class-specific validators as sub-classes within the class they decorate to emphasize the tight coupling to the class itself.  But you may want to keep them elsewhere if you don't like the idea of validator classes polluting the class they're validating.  And if you're making more general purpose validators which can be used by various classes, I typically throw them into MyProject.Core/Validators for keeping them accessible from one place.

For S#arp Architecture users, I frequently always have a need to create validatable DTOs; a useful base class for these DTOs is as follows:

public class ValidatableDto : IValidatable
{
    public virtual bool IsValid() {
        return Validator.IsValid(this);
    }

    public virtual ICollection ValidationResults() {
        return Validator.ValidationResultsFor(this);
    }

    private IValidator Validator {
        get {
            if (validator == null) {
                validator = SafeServiceLocator.GetService();
            }

            return validator;
        }
    }

    [ThreadStatic]
    private static IValidator validator;
}

Happy coding!

Billy McCafferty
http://www.itsamuraischool.com


Posted 07-30-2009 3:42 PM by Billy McCafferty

[Advertisement]

Comments

9eFish wrote Writing a Custom NHibernate Class Validator - Billy McCafferty - Devlicio.us
on 07-30-2009 11:20 PM

9efish.感谢你的文章 - Trackback from 9eFish

DotNetShoutout wrote Writing a Custom NHibernate Class Validator - Billy McCafferty - Devlicio.us
on 08-01-2009 6:56 PM

Thank you for submitting this cool story - Trackback from DotNetShoutout

W3Max wrote re: Writing a Custom NHibernate Class Validator
on 08-21-2009 8:27 PM

Thank you for post!

If your creating validation rules for your DTOs does it mean that you duplicate some validation applied to your model objects?

What would be the validation life-cycle of a Create Action (MVC) that creates a/some DTOs, pass the DTOs to an Application Service that creates a model object from the DTOs?

Billy McCafferty wrote re: Writing a Custom NHibernate Class Validator
on 09-07-2009 5:02 PM

"It all depends" is the simple answer.  Certainly, it can be surmised that there would be some situations wherein very different validation rules would be applied to DTOs rather than domain objects; so there may be no duplication whatsoever.  Also, if you're looking to use the same, custom validator in multiple places then it can be moved to its own reusable class.

Could you be more specific about your question concerning the validation life-cycle?  I'm not sure I understand what you're looking for.

salhdenecl wrote re: Writing a Custom NHibernate Class Validator
on 09-14-2009 4:47 PM

national developer gross bush further conclusions

marie macphee ne macleod wrote re: Writing a Custom NHibernate Class Validator
on 09-22-2009 4:14 PM

are you the same billy maccaferty that was in skye a FEW years back. i think you maybe look like him from the small photo of you.

Billy McCafferty wrote re: Writing a Custom NHibernate Class Validator
on 09-22-2009 4:18 PM

Hi Marie,

If you're talking about Skye, as in the Inner Hebrides of Scotland, then it wasn't me...never been there.  Sounds like a nice place to visit though!

Billy

marie macphee ne macleod wrote re: Writing a Custom NHibernate Class Validator
on 09-22-2009 4:58 PM

well it was worth a try . thanks. yes skye is a lovely place . you should visit.   cheers marie

Pharme615 wrote re: Writing a Custom NHibernate Class Validator
on 11-27-2009 3:46 AM

Very nice site!

Pharmc984 wrote re: Writing a Custom NHibernate Class Validator
on 12-17-2009 7:38 PM

Very nice site!

Pharmd681 wrote re: Writing a Custom NHibernate Class Validator
on 01-01-2010 2:42 PM

Very nice site!

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)