While looking for something totally different the other day, I have stumbled upon two libraries for doing Fluent Validation in .NET. The concept seems interesting since so far I am doing my validations using the usual conditional and branching statements (if, else, case, etc).
In particularly, it makes relatively easy to chain some conditions which could result in some cases in shorter code for complex conditions, and to embed several error messages for each violations in the same object.
That said, isn't it also making the code look more verbose than C# usually is, a bit like T-SQL can be at times... and doesn't this cause the code to have an inconsistent look and feel?
In short, what do you think of Fluent Validation and if you like it, which library have you found to be the best for it? So far, I have looking at http://tnvalidate.codeplex.com/ and http://fluentvalidation.codeplex.com/ which s开发者_如何学Goeem more or less equivalent at the first glance...
Thanks.
There is also http://rulesengine.codeplex.com/ Which uses a fluent-interface helper class to add rules to an engine (which is then used to validate objects).
Supports Composition, Cross-Field, Conditional, multi-languages, etc...
I'm using my own validation library that I've published here.
The difference with the two that you suggested is that the validations are put into separate validation classes. You can create and forget the validation classes, they are automatically discovered by the validation library.
public class MyModelValidator : FluentValidator<MyModel>
{
public MyModelValidator()
{
Property("FirstName").Required();
Property("LastName").Required().Min(15);
}
}
It's also easy to add support for localizations using your very own favorite localization libray (such as a string table)
public class StringTableProvider : ILanguagePrompts
{
public string this[string modelName, string propertyName]
{
get { return Get(modelName, propertyName) ?? "[" + propertyName+ "]"; }
}
public string Get(string modelName, string propertyName)
{
return Resource1.ResourceManager.GetString(modelName + "_" + propertyName);
}
}
And to configure:
Validator.LanguageHandler = new StringTableProvider();
The actual validation is done like this:
User user = new User();
user.FirstName = "Jonas";
var errors = Validator.Validate(user);
if (errors.Count > 0)
{
// Handle the errors in any way you like.
// both property names (localized and actual property name) and localized error message is accessible.
}
I stumbled into something similar on my own, and I wrote it precisely so the code would be LESS verbose.
I have my own validation where I do things like:
Validation.IsNullOrEmpty(m => m.FirstName, modelState);
Validation.Validate(m => m.ZipCode, z => z.Length == 5, modelState,
"ZipCode must be 5 characters long");
Now this is tied very closely to the MVC architecture I'm using, but I find that to be easier to read and maintain than:
if (string.IsNullOrEmpty(FirstName))
{
ModelState.AddError("FirstName", "FirstName cannot be empty.");
}
In this context, it's not so noticeable, but when you do validation, you can have MANY items to validate, so the one liners become much easier to scan and figure out what the validation is doing.
You do have the first time where you run into the first code I put up there and you have to figure out what's going on, but once you get past that, I think a bunch of one liners are easier on the eyes than the multiple blocks the second method will produce.
精彩评论