Simple.Validation 0.4.0–Release Notes
New Features
Added an assertion api to the PropertyValidator so that the Properties<T> api can be extended by clients.
The order of operations for the Properties api is as follows: If(), Required(), Assertions().
As an example, customized support for boolean properties was added to the library using the following code:
public static class BooleanPropertyExtensions { public static PropertyValidator<TContext, bool> IsTrue<TContext>(this PropertyValidator<TContext, bool> self) { self.Assert((t, p) => p); return self; } public static PropertyValidator<TContext, bool> IsFalse<TContext>(this PropertyValidator<TContext, bool> self) { self.Assert((t, p) => !p); return self; } public static PropertyValidator<TContext, bool?> IsTrue<TContext>(this PropertyValidator<TContext, bool?> self) { self.Assert((t, p) => p.GetValueOrDefault()); return self; } public static PropertyValidator<TContext, bool?> IsFalse<TContext>(this PropertyValidator<TContext, bool?> self) { self.Assert((t, p) => p.HasValue && !p.Value); return self; } }
Breaking Changes
RangePropertyValidator has been removed. It’s functionality is still available, but it has been entirely replaced by extension methods that use the new Assert() method on the PropertyValidator.
ValidationResultTypes have been completely removed. Then intent for ValidationResult.Type is that it is custom per project.
What’s new in Simple.Validation 0.3.1?
Silverlight 4
The entire Simple.Validation library has been compiled for Silverlight and included in the NuGet package.
Conditional Property Validators
An If() method has been applied to the following property validators:
- EnumerablePropertyValidator
- RangePropertyValidator
- ReferencePropertyValidator
- StringPropertyValidator
When If() is called with the required Predicate, the validator will only apply when the condition specified by the Predicate is met.
[Test]
public void If_PredicateIsFalse_ShouldNotValidate()
{
// Arrange
var validator = Properties<Employee>
.For(e => e.Age)
.GreaterThanOrEqualTo(18)
.If(e => e.Age != -1)
;
// Act
var employee = new Employee()
{
Age = -1
};
var results = validator.Validate(employee);
// Assert
Assert.That(results, Is.Empty);
}
Simple.Validation v0.2.3
A new release of Simple.Validation is available on NuGet.
The changes include:
- Fluent Properties API
- AncestorTypeValidator
- CompositeValidator
- EnumerablePropertyValidator
- ReferencePropertyValidator
While Simple.Data is not intended to focus on property-level validation so much that more complex validation scenarios are difficult, it must be recognized that property-level validation accounts for a large part of validation scenarios. In keeping with the goal of simplicity, Simple.Validation provides some mechanisms for wiring up property-level validations quickly. The Fluent Properties API provides factory methods for creating validators for common property types. When used in conjunction with the CompositeValidator<T> it is a trivial task to get simple property-level validation implemented quickly.
This code is from the Personnel.Sample project included in the source code.
public class SaveAddressValidator : CompositeValidator<Address> { public override bool AppliesTo(string rulesSet) { return rulesSet == RulesSets.Crud.Save; } protected override IEnumerable<IValidator<Address>> GetInternalValidators() { yield return Properties<Address>. For(a => a.Line1) .Length(0, 50) .Required() .Message("Address Line 1 is required."); yield return Properties<Address> .For(a => a.Line2) .Length(0, 50) .NotRequired() .Message("Line 2 must be between 0 and 50 characters in length."); yield return Properties<Address> .For(a => a.Line3) .Length(0, 50) .NotRequired() .Message("Line 3 must be between 0 and 50 characters in length."); yield return Properties<Address> .For(a => a.PostalCode) .Length(0, 20) .NotRequired() .Message("Postal Code must be between 0 and 20 characters in length."); yield return Properties<Address> .For(a => a.Country) .Length(0, 3) .NotRequired() .Message("Country must be between 0 and 3 characters in length."); yield return Properties<Address> .For(a => a.StateOrProvince) .Length(0, 50) .NotRequired() .Message("StateOrProvince must be between 0 and 50 characters in length."); } }
In this sample, each call to Properties<T>.For() returns an instance of StringPropertyValidator. CompositeValidator will accumulate the results from each of the property-level validators and return them all as a single result set. What about non-string properties?
public class SaveEmployeeValidator : CompositeValidator<Employee> { public override bool AppliesTo(string rulesSet) { return rulesSet == RulesSets.Crud.Save; } protected override IEnumerable<IValidator<Employee>> GetInternalValidators() { yield return Properties<Employee> .For(e => e.FirstName) .Length(3, 50) .Required() .IgnoreWhiteSpace(); yield return Properties<Employee> .For(e => e.LastName) .Length(3, 50) .Required() .IgnoreWhiteSpace() ; yield return Properties<Employee> .For(e => e.Age) .MinValue(18) .MaxValue(65) ; yield return Properties<Employee> .For(e => e.Address) .Required() .Cascade("Save") ; yield return Properties<Employee> .For(e => e.ContactInfo) .Required() .Count(1) .Unique<ContactInfo>(c => c.Type) .Cascade("Save"); } }
Employee.Age is of type Int32. Properties<T>.For() any property that is convertible to IComparable will return an instance of RangePropertyValidator. If the property is a reference type, it will return an instance of ReferencePropertyValidator, and if it’s a collection type it will return an instance of EnumerablePropertyValidator.
ReferencePropertyValidator and EnumerablePropertyValidator are similar in that they support Cascading validation onto the reference or collection property itself. This means that Valdiator.Validate<T> will be called for the value of the reference property, or for each element of the collection property. The results will be accumulated into the overall validator results.
When performing cascade validation, there is some question about the type that should be passed to Validator.Validate<T>. Should it be the declared property type (or declared type of the elements of the collection), or should Simple.Validation use the actual type of the property value (or collection element). By default, Cascade() uses the actual type of the property value or collection element, but you can specify the usage of a base type or interface by using the Cascade<T> overload.
In the Personnel.Sample project EmailAddress inherits ContactInfo. There is an EmailAddressValidator that tests the email address against a regular expression. If an instance of EmailAddress is added to the Employee.ContactInfo collection, should it be validated using the EmailAddressValidator or the ContactInfoValidator? Calling the non-generic Cascade() method will cause it to be validated using EmailAddressValdiator. Calling Cascade<ContactInfo>() will cause it to be validated only by the SaveContactInfoValidator.
Announcing Simple.Validation
My company has graciously allowed me to develop a lightweight validation framework and publish it as open-source. There are other very nice validation frameworks available, so why another one? I wanted to be able to use something with all of the strengths and none of the weaknesses of the existing libraries. Here are my stated goals for the project:
- Simplicity
- Get moving with a minimum number of moving parts
- Support dependency injection
- Focus on object-level validation
- Support for common property-level validation
- Support all application types in a consistent manner
- Support validation at all application layers in a consistent manner
- Pluggable Architecture
The api I wanted for usage was very simple. Here’s some code from the LoanApplicationSample project:
public class LoanApplicationDb { public void Save(LoanApplication loanApplication) { Validator.Enforce(loanApplication, "Save"); // do save logic } public void Submit(LoanApplication loanApplication) { Validator.Enforce(loanApplication, "Save", "Submit"); // do submit logic } }
Just pass your object to the Valdiator.Enforce() method along with the rules sets you wish to validate against and you are off to the races. Enforce will call Validator.Validate(), check for errors, and throw a ValidationException if it finds any. If it doesn’t find any, it just returns the results of Validate(). If you want to bypass the exception logic, just call Validate() directory.
The above code sample demonstrates how to consume the Validator API, but how do you plug into it? You need to be aware of two components. The first is the IValidator<T> implementation. Here is a sample validator that validates the LoanApplciation against the “Save” rules set.
public class SaveLoanApplicationValidator : IValidator<LoanApplication> { public bool AppliesTo(string rulesSet) { return rulesSet == "Save"; } public IEnumerable<ValidationResult> Validate(LoanApplication value) { var nameResults = Properties<LoanApplication> .For(e => e.Name) .Required() .Length(2, 100) .Message("Name is required.") .IgnoreWhiteSpace() .Validate(value) ; var reasonResults = Properties<LoanApplication> .For(e => e.Reason) .Required() .Length(10, 500) .IgnoreWhiteSpace() .Message("Reason is required.") .Validate(value) ; var accumulatedResults = nameResults .Concat(reasonResults) ; return accumulatedResults; } }
This validator uses the built-in PropertyValidator fluent syntax. Use of the built-in validators is entirely optional. They are included as a convenience in order to provide support for common property-level validations. Simple.Validation handles the simple stuff for you
. Where many validation frameworks fall down is when there is some kind of complex validation. In Simple.Validation, complex scenarios are handled the same way as property-level validation. Here’s an example:
public IEnumerable<ValidationResult> Validate(LoanApplication value) { if (someComplexCondition) yield return new ValidationResult() { Context = value, Message = string.Format(messageFormat, arguments), PropertyName = "PropertyName", Severity = ValidationResultSeverity.Error, Type = MyCustomValidationType.SomeComplexConditionError };
The ValidationResult is a fairly rich object containing a lot of information about the validation error. The Context is the object being validated. You can (and should) provide a detailed message about the error. PropertyName is not required, but will be useful in many scenarios. Severity has levels of Error, Warning, and Informational. ValidationResult.Type is a property there for arbitrary categorization of validation results.
Okay, so now I’ve written a validator—but how does the static Validator class know about the validator I just wrote?
Validator uses an instance of IValidatorProvider to get the list of validators from the simple. Simple.Validation ships with a DefaultValidatorProvider which you can use as follows:
public class Configuration { public void ConfigureValidation() { var validatorProvider = CreateValidatorProvider(); RegisterValidators(validatorProvider); Validator.SetValidatorProvider(validatorProvider); } private static void RegisterValidators(DefaultValidatorProvider validatorProvider) { validatorProvider.RegisterValidator(new SaveLoanApplicationValidator()); validatorProvider.RegisterValidator(new SubmitLoanApplicationValidator()); } private static DefaultValidatorProvider CreateValidatorProvider() { var validatorProvider = new DefaultValidatorProvider(); return validatorProvider; } }
The implementation of DefaultValidatorProvider is naïve, so you are encouraged to use the IValidatorProvider interface as a wrapper around your favorite Dependency Injection framework. We provide a second nuget package called Simple.Validation.Ninject that contains a NinjectValidatorProvider.
We’ve been using Simple.Valdiation internally for awhile and feel pretty good about its release. However, as it hasn’t been published on the public NuGet feed yet, we’re assigning a prelease version of 0.1. We will conform to semantic versioning conventions as outlined in this post from Phil Haack.
So, run Install-Package Simple.Validation from the Visual Studio Package Manager Console and start using the bits! As always, your feedback is much appreciated.
Happy Coding! ![]()
Isg.Specification
I was reading some interesting blogs on the specification pattern today. I was hoping to find a NuGet package, but no such luck. So, I put together the best ideas from the blogs I read and created a new NuGet package called Isg.Specification. Much of this work is not original—my contribution is putting the work of these other developers together in an integrated way and publishing it on NuGet.
Although the write-up of the specification pattern on wikipedia doesn’t mention my specific usage goal, I want to create a parameter object that provides a specification to be used by a LINQ query in EntityFramework. In this way, I can provide a single Get<T>(ParameterObject specification) method to service all Get queries. This simplifies a service interface by removing all the various GetById, GetByName, GetByHasInvoices methods. All that differs between those methods is the predicate applied to the query, so passing the predicate into Get() as a parameter just feels natural. However, I don’t want the caller to be able to specify any predicate they want so using a parameter object that converts itself into a predicate services the purpose of limiting the callers query access as well as simplifying the query API.
Even though my target usage is EntityFramework, and the source code is in the same repository as Isg.EntityFramework, Isg.Specification in no way depends on EntityFramework.
The simplest form of the specification pattern uses simple boolean functions. However, since my target usage is EntityFramework, I needed the functions to be convertible to SQL by the EntityFramework. For this reason, my implementation of ISpecification<T> uses Expression<Func<T, bool>> instead of Func<T, bool> as its signature.
1: public interface ISpecification<T>
2: {
3: Expression<Func<T, bool>> IsSatisfied();
4: }
The simplest way to get started using the library is to inherit from CompositeSpecification<T>. Using the same sample DbContext I used for Isg.EntityFramework, here is a sample implementation of a Specification object against Customer:
1: public class CustomerSpecification : CompositeSpecification<Customer>
2: {
3: public string Name { get; set; }
4: public bool? HasInvoices { get; set; }
5:
6: protected override IEnumerable<Expression<Func<Customer, bool>>> GetExpressions()
7: {
8: if (!string.IsNullOrWhiteSpace(Name))
9: yield return ByName();
10:
11: if (HasInvoices.HasValue)
12: yield return ByHasInvoices();
13: }
14:
15: private Expression<Func<Customer, bool>> ByHasInvoices()
16: {
17: if (HasInvoices.Value)
18: return c => c.Invoices.Any();
19: return c => !c.Invoices.Any();
20: }
21:
22: private Expression<Func<Customer, bool>> ByName()
23: {
24: return c => c.Name.StartsWith(Name);
25: }
26: }
Usage is pretty easy. ISpecification<T> exposes a single method called IsSatisfied(). Feed the result of this method to a LINQ Where clause and you’re off to the races. CompositeSpecification<T> aggregates the expressions provided by GetExpressions() into a single And-ed expression and uses that for the filter.
In my test cases I create 2 customers, one of whom has invoices and one who does not. You can review the test cases in full here:
Here is sample usage:
1: [Test]
2: public void HasInvoices()
3: {
4: // Arrange
5: var filter = new CustomerSpecification()
6: {
7: HasInvoices = true,
8: };
9:
10: // Act
11: using (var context = new CustomerDbContext())
12: {
13: var query = context.Customers
14: .Where(filter.IsSatisfied())
15: .ToList();
16:
17: // Assert
18: Assert.That(query, Has.Count.EqualTo(1));
19: var result = query.Single();
20: Assert.That(result.Name, Is.EqualTo("Dagny Taggart"));
21: }
22: }
Interesting Blogs on the Specification Pattern
I just wanted to give some link-love to the blogs that were helpful to me in implementing the Specification Pattern. Stay tuned for Isg.Specifications on NuGet!
http://davedewinter.com/2009/05/31/linq-expression-trees-and-the-specification-pattern/
http://blogs.msdn.com/b/meek/archive/2008/05/02/linq-to-entities-combining-predicates.aspx
http://iainjmitchell.com/blog/?p=550
http://huyrua.wordpress.com/2010/07/13/entity-framework-4-poco-repository-and-specification-pattern/
http://devlicio.us/blogs/jeff_perrin/archive/2006/12/13/the-specification-pattern.aspx
Isg.EntityFramework 0.4.2 Released to NuGet
Isg.EntityFramework.Interceptors was renamed to Isg.EntityFramework. The interceptors are still present, but I’ve added some work around EntityFramework Configuration.
Changes:
- InterceptorDbContext is obsolete. Please use Isg.EntityFramework.DbContextBase
- DbContextBase adds support for a ModelConfigurationProvider
- The default ModelConfigurationProvider scans the assembly that your DbContextBase subclass lives in and finds all instances of EntityTypeConfiguration<> and loads them.
- I added some extension methods to make specifying a non-identity primary key column and computed column a little more straightforward. The EntityFramework method works fine, but isn’t very discoverable. Now it’s Property(<expression>).IsIdentity(false) and Property(<expression>).Computed().
- Isg.EntityFramework is built against EntityFramework 4.3
Isg.EntityFramework is growing slowly but surely. I would love to hear your ideas about what features you would like to see.
Enjoy!
Isg.Collections Now Includes EachConsecutive().
This morning at #SCNA Michael Feathers (@mfeathers) showcased an interesting Ruby function each_cons(). At first glance I didn’t think the function was all that useful, but then he showed how you could use it to see if a list is sorted. I couldn’t find a .NET implementation anywhere, so I added it to my Isg.Collections NuGet package as EachConsecutive().
The algorithm relies on knowing the count of items in its source enumerable. This requires that the enumerable be materialzied. I didn’t want to create deferred execution on Enumerable, so the extension method operates on ICollection<T> instead of IEnumerable<T>.
Here’s some sample code:
// Arrange: Declare any variables or set up any conditions // required by your test. var array = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // Act: Perform the activity under test. var isSorted = array.EachConsecutive() .All(pair => { var left = pair.First(); var right = pair.Last(); return left < right; }); var isNotSorted = array .Reverse() .ToArray() .EachConsecutive() .All(pair => { var left = pair.First(); var right = pair.Last(); return left < right; }); // Assert: Verify that the activity under test had the // expected results Assert.That(isSorted, Is.True); Assert.That(isNotSorted, Is.False);
Skyrim: First Impressions (PC Version)
It should go without saying that Skyrim is a beautiful game. The visuals are highly detailed and fantastic. However, a game can be pretty and boring too.
The gameplay in Skyrim is very good. My favorite new feature is that you can “dual-cast” a spell by assigning it to both hands. This makes the spell more powerful. You can also augment your character with “perks,” which are similar to Feats in 3rd and 4th edition D&D. The crafting system seems richer than in previous games at first glance. For example, you can cure the pelts from animals you kill into leather. Leather can be cut into strips. Leather strips can be used as components are arms and armor you create.
The UI in Skyrim could be a little better in my opinion. First, the tutorial doesn’t really tell you how important the Tab key is. It basically gets you into and out of your character. Gone is the grid image of your backpack (which is fine). Instead you just have a long list of items. You can click on item categories to get sublists, but the items are just sorted alphabetically. It’s hard to see everything your character has equipped. It would be nice to be able to sort items by weight or value. You still have to play the game of deciding which loot to keep and sell and which gear to drop. It’s harder when you can’t sort by weight and value.
You can select gear, skills, and spells and add them to a “favorites” menu. Pressing ‘Q’ at any time during the game brings up the favorites menu allowing you to use potions or switch out weapons or spells. This is pretty cool, but there doesn’t seem to be a way to hotkey certain items. I know I’ve wished for a healing potion hotkey during combat. On the other hand, entering the favorites menu does pause the action, so there’s no penalty for having to search through your favorites for the healing potion.
Another thing that’s new is the ability to hire followers. I asked an archer to accompany me and he’s helped me through some difficult combat scenarios. The only drawback to the followers is that they are sometimes in the way. Much of the interaction with NPC’s is scripted, and if the follower is standing in the NPC’s path the NPC isn’t usually smart enough to go around. Instead I have to move around a bit to get my follower to move out of the NPC’s way.
The story is interesting so far. I’ve got about 4 hours in the game at this point. There are other gameplay elements that I haven’t mentioned for fear of giving spoilers. In the entire 4 hours I played, I had no game crashes or obvious bugs of any kind. I purchased a copy of the game through Steam.
Using the EntityFramework SoftDelete Interceptor
In my previous post I introduced the Isg.EntityFramework.Interceptors I created. In this post, I will demonstrate the usage of another package that builds on the first: Isg.EntityFramework.Interceptors.SoftDelete
The entire SoftDelete package consists of two classes. The first is an interface:
1: public interface ISoftDelete
2: {
3: bool IsDeleted { get; set; }
4: }
The second is the SoftDeleteChangeInterceptor class.
If your domain class implements ISoftDelete, the SoftDeleteChangeInterceptor will catch the delete operation, set the IsDeleted field to true, and repurpose the operation to an Update.
Here is a unit test that demonstrates this behavior.
1: [Test]
2: public void Delete()
3: {
4: var name = Guid.NewGuid().ToString();
5:
6: using (var db = new CustomerDbContext())
7: {
8: var customer = new Customer {IsDeleted = false, Name = name};
9: db.Customers.Add(customer);
10: db.SaveChanges();
11: }
12:
13: using (var db = new CustomerDbContext())
14: {
15: var customer = db.Customers.SingleOrDefault(i => i.Name == name);
16: db.Customers.Remove(customer);
17: db.SaveChanges();
18: }
19:
20: using (var db = new CustomerDbContext())
21: {
22: var customer = db.Customers.SingleOrDefault(i => i.Name == name);
23: Assert.That(customer, Is.Not.Null);
24: Assert.That(customer.IsDeleted, Is.True);
25: }
26: }
Happy Coding!