Validation of user input is very important. A lot of our users are very environmentally aware and throw all kinds of garbage in (= garbage out). So you probably better use extensive validation for all your dataclasses (or Business Entities, if you like). A consequence is that you have to invoke validation almost everywhere in your business logic. That’s a lot of boooooring repetitive work.
To me this smells like a cross-cutting ‘AOP’ concern, i.e. use Policy Injection.
In the following example of validation “the AOP way” I show you how to use Validation with Policy Injection, which are both part of Enterprise Library.
For simplicity we are going to validate a very simple Customer class, which still is very realistic. Even in the real world you can come across some really simple customers, like this one:
“I do not want to pay a penny extra for validation. When I buy me an application I expect that you deliver one fully validated without errors in it. So if you want validation, please do it at your own expense.”
Yes, this customer is in heavily need of managing customer expectation, but that’s a different story.
The how-to example is build around a Factory Design pattern (Customer, interface IRepository, and concrete class CustomerRepository) and accessed via Facade pattern (CustomerManager). I use a facade here, because then you do not not have to reference parts of Enterprise Library in your client code. Enterprise Library can stay within a single class library together with the other stuff. Isolation of the chosen technical implementation. In this way we can easily replace it with a better implementation, if we don’t like Policy Injection any more.
|
1 2 3 4 5 6 7 8 9 10 11 |
public class Customer { string m_FullName; [StringLengthValidator(5)] public string FullName { get { return m_FullName; } set { m_FullName = value; } } } |
The property FullName is decorated with a validation attribute StringLengthValidator. Upon validation it is checked if the length of the string does not exceed 5. I know, silly validation.
The client code is as follows, it just calls the CustomerManager facade:
|
1 2 3 4 5 6 |
CustomerManager mgr = new CustomerManager(); Customer customer = new Customer(); customer.FullName = "thisisaverylongname"; bool IsValid = mgr.Save(customer); |
The CustomerManager façade:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public bool Save(Customer customer) { bool IsValid = false; IRepository ctr = PolicyInjection.Create(); try { ctr.Save(customer); IsValid = true; } catch (ArgumentValidationException ex) { ValidationResults results = ex.ValidationResults; // ... } return IsValid; } |
Finally, the interface IRepository and its concrete class CustomerRepository:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
//IRepository interface: interface IRepository { [ValidationCallHandler] void Save(Customer customer); } class CustomerRepository : IRepository { void IRepository.Save(Customer customer) { // Saving logic... } } |
With this concrete example at hand you should have a start of and be able to experiment a little bit with validation the AOP way.
If you need some extra help with the above example or have a strong opinion towards use of the Policy Injection, just leave a comment.
Comments