SpecExpressImplementation

First of all this implementation is not using the EntityFramework that we will probably go to in future releases. Rather it is an elegant addition to our current hack (e.g. the ongoing effort to organize the growing mire into something other than the big ball of mud).

Procedure for implementation on each Data Object

Step 1: Write the Specification

A specification looks like this:

    public class PartIdentificationDataSpecification : Validates<PartIdentificationData>
    {
        public PartIdentificationDataSpecification()
        {
            IsDefaultForType();
            Check(c => c.locusIdentity).Required();
            Check(c => c.locusNumber).Required().GreaterThan(0);
            Check(c => c.site).Required();
            Check(c => c.season).Required();
            Check(c => c.field).Required();
            Check(c => c.square).Required();
            Check(c => c.DateStart).Required();
            Check(c => c.DateEnd).Optional();
            Check(c => c.supervisor).Required();
            Check(c => c.balk).Optional();
            Check(c => c.designation).Optional();
        }
    }

Step 4: Modify the Controls for each object

For each object there are "Controls" that were POCO that must be changed into inheriting from UserControl. This is necessary to validate properly (don't ask its a long story).

  1. Inherit form UserControl (01)

  2. Add a private System.ComponentModel.IContainer components (02)

  3. Create a constructor that calls InitializeComponent() - this is a change from what we have done. We always did want to make these identical in that sense. So do it now! (03)

  4. Now, change the name of Initialize... to InitializeComponent and make the changes shown in (04)

Now you have a real component that can be used as such in the future.

     ...
(01) public class IdentificationControls : UserControl

     ...

(02) private System.ComponentModel.IContainer components;

     ...

(03) public IdentificationControls()
     {
         InitializeComponent();
     }

     ...

(04) public void InitializeComponent()
     {
         components = new Container();

         ...

         //Add the controls to the user control
         Controls.AddRange(new System.Windows.Forms.Control[]
         {
             this.panelIdentification
         });
     }


=== Step 3: Implement Verification in the BusinessObject (those under Data) ===

 1. Add the IDataErrorInfo interface to the Class (01)
 1. Add a new property: string Error (02)
 1. Add two private variables: BindingSource myBindingSource (03) and ErrorProvider myErrorProvider (04)
 1. Add instantiation of the two new private variables and set their values as shown in in (05) - (09). This effectively binds the graphic elements of the component to this object and allows the IDataErrorInfo to worry about the validation. 
 1. Add the required interface method in the Interface Methods region (10) - (11). This is what actually calls the Spec Express Framework.

{{{
01   public class PartIdentificationData : IDataErrorInfo

   ...

02   //for validation purposes
     public string Error
     {
        get
        {
            return _lastError;
        }
     }

   ...

03   private BindingSource myBindingSource;
04   private ErrorProvider myErrorProvider;

   ...

   private void buildControl()
   {
       //The next two lines create a BindingSource for validation purposes
05     myBindingSource = new BindingSource();
06     myBindingSource.DataSource = this;
       

       //Get the "View"
       IdentificationControls idcs = new IdentificationControls();
       idcs.InitializeIdentificationControls();
       idCtrl = idcs.panelIdentification;

       //Create an Error Provider to show errors to the user.
07     myErrorProvider = new ErrorProvider();
08     myErrorProvider.DataSource = myBindingSource;
09     myErrorProvider.ContainerControl = idcs;

   ...

10 #region Interface Methods

   public string this[string fieldName]
   {
       get
       {
          try
          {
               switch (fieldName)
               {
                   case "Error": return _lastError;
                   default:
                       _lastError = ValidationExpressions.getErrorMessage(this, fieldName);
                       break;
               }
           }
           catch (Exception ae)
           {
               System.Windows.Forms.MessageBox.Show("PartIdentificationData through an exception while trying to validate Filed\"" + fieldName + "\"\n\n" + ae.Message);
           }
           return _lastError;
       }
   }

11 #endregion