Friday, May 28, 2010

Dependency injection and Microsoft Enterprise Library validation app block

Sometimes, when you use EntLib (Microsoft Enterprise Library) validation block, you may realize, that the built-in set of validators in the EntLib does not satisfy all the your needs. Of course, you can create a custom validation, inheriting from the abstract Validator and ValidationAttribute classes. This is a good way to create a validation logic, that can be used in the different parts of your project. But what to do, if you need to access  some business components inside of validator, which should be resolved via the dependency injection (DI) mechanism? Since the EntLib is responsible for instantiating validators instances, it doesn`t know anything about your registered dependency classes, and will not be able to resolve such dependencies. In this case you have two possible solutions:
  • Access DI container via a static class, that has a reference to it;
  • Use SelfValidationAttribute in the class you have to validate;
I do not recommend the first approach with a static class, because it makes your domain model dependent on the application infrastructure. From my point of view, the less classes know about dependency injection container - the better. The second approach is more prefferable, it is very suitable for the progressive domain models and view-models from the MV-VM pattern. All that you need to do is:
  1. Define in your class a public void method that takes a single parameter of type ValidationResults;
  2. Decorate this method with a SelfValidationAttribute;
  3. Decorate your class with a HasSelfValidationAttribute;
Let`s consider the following example. We have a CreateProductViewModel class that is used for representing a product creation form to user. Let`s assume, that we want to deny user to create a new product, if there is a product with the same name already exists in the store database. Moreover, we want to use a business component, which is responsible for the product-related operations. Since we have a large composite application, we use a DI mechanism to provide a loosely coupled architecture and increase testability. Below you can find the code of this sample class.

  1. [HasSelfValidation]
  2. public class CreateProductViewModel
  3. {
  4.   private readonly IProductComponent
    _productComponent;
  5.  
  6.   public CreateProductViewModel(IProductComponent productComponent)
  7.   {
  8.     _productComponent = productComponent;
  9.   }
  10.  
  11.   [StringLengthValidator(1, 20)]
  12.   public string ProductName { get; set; }
  13.  
  14.   [SelfValidation]
  15.   public void
    IsDuplicateProductName(ValidationResults results)
  16.   {
  17.     var product =
    _productComponent.GetProductByName(ProductName);
  18.  
  19.     if (product != null)
  20.       results.AddResult(new ValidationResult("Product with same name already exists", null,
    "ProductName",
  21.                          
    null, null));
  22.   }
  23. }
* This source code was highlighted with Source Code Highlighter.
Here is the IsDuplicateProductName method that performs a validation logic by acquiring a product component. Product component is an instance of the class, which implements IProductComponent interface and most probably becomes resolved via the constructor dependency injection, but this is not so significant. You can get full validation results by invoking the code like this:

  1. var validator = ValidationFactory.
    CreateValidatorFromAttributes<CreateProductViewModel>();
  2.  
  3. ValidationResults results;
  4. validator.Validate(createProductViewModelInstance, results);
* This source code was highlighted with Source Code Highlighter.

No comments:

Post a Comment