PostSharp 4.3 / / Post­Sharp Documentation / Standard Patterns / Contracts / Walkthrough: Adding Contracts to Code
Walkthrough: Adding Contracts to Code

This section describes how to add a contract to a field, property, or parameter.

This topic contains the following sections:

Introduction

Consider the following method which checks if a valid string has been passed in:

C#
                        public
                         
                        class
                         CustomerModel
{
  
                        public
                         
                        void
                         SetFullName(
                        string
                         firstName, 
                        string
                         lastName)
  {
      
                        if
                        (firstName == 
                        null
                        )
        
                        throw
                         NullReferenceException();

      
                        if
                        (lastName == 
                        null
                        )
        
                        throw
                         NullReferenceException();

      
                        this
                        .FullName = firstName + 
                        " "
                         + lastName;
  }
}
                      

In this example, checks have been added to ensure that both parameters contain a valid string. A better solution is to place the logic which performs this check into its own reusable class, especially such boilerplate logic is involved, and then reuse/invoke this class whenever the check needs to be performed.

PostSharp’s Contract attributes do just that by moving such checks out of code and into parameter attributes. For example, PostSharp’s RequiredAttribute contract could be used to simplify the example as follows:

C#
                        public
                         
                        class
                         CustomerModel
{
    
                        public
                         
                        void
                         SetFullName([Required] 
                        string
                         firstName, [Required] 
                        string
                         lastName)
    {
        
                        this
                        .FullName = firstName + 
                        " "
                         + lastName;
    }
}
                      

In this example the RequiredAttribute attribute performs the check for null, thus eliminating the need to write the boiler plate code for the check inline with other code.

A contract can also be used in a property as shown in the following example:

C#
                        public
                         
                        class
                         CustomerModel
 {
    [Required]
    
                        public
                         FirstName
    {
        
                        get
                        ;
        
                        set
                        ;
    }
}
                      

Using a contract in a property ensures that the value being passed into set is validated before the logic (if any) for set is executed.

Similarly, a contract can be used directly on a field which will validate the value being assigned to the field:

C#
                        public
                         
                        class
                         CustomerModel
{
    [Required]
    
                        private
                         
                        string
                         mFirstName = “Not filled 
                        in
                         yet”;

    
                        public
                         
                        void
                         SetFirstName(
                        string
                         firstName)
    {
        mFirstName = firstName;
    }
}
                      

In this example, firstName will be validated by the Required contract before being assigned to mFirstName. Placing a contract on a field provides the added benefit of validating the field regardless of where it’s set from.

Note that PostSharp also includes a number of built-in contracts which range from checks for null values to testing for valid phone numbers. You can also develop your own contracts with custom logic for your own types as described below.

There are two ways to add contracts:

Adding contracts using PostSharp Tools for Visual Studio

PostSharp’s Visual Studio integration provides a smart tag popup which can be used to select and apply a contract to a parameter, field, or property.

To add contract using PostSharp Tools for Visual Studio:

  1. Click on the parameter, field, or property for which the contract is to be applied. While hovering the mouse over this item, a smart tag drop-down will appear:

    Adding Contracts 1
  2. Click on the smart tag drop-down to reveal the contracts available:

    Adding Contracts 2
  3. Select a contract from the list or select Add another aspect to display the aspect selection dialog:

    Adding Contracts 3
  4. Select a contract and click Next.

  5. Confirm the addition of the contract and click Next:

    Adding Contracts 4
  6. Click Finish when the dialog indicates that the operation completed:

    Adding Contracts 5

The aspect has now been added in code:

Adding Contracts 6
Adding contracts manually

To add contract manually:

  1. Add the PostSharp.Patterns.Model assembly to your project.

  2. Add the namespace containing the code contacts you plan to use.

    You can find a full list of available ready-made patterns in the documentation of the PostSharp.Patterns.Contracts namespace.

  3. Add the attribute before the parameter name. For example:

    C#
                                  public
                                   
                                  void
                                   SetFullName([Required] 
                                  string
                                   firstName, [Required] 
                                  string
                                   lastName)
                                
Contract Inheritance

PostSharp ensures that any contracts which have been applied to an abstract, virtual, or interface method are inherited along with that method in derived classes, all without the need to re-specify the contract in the derived methods. This is shown in the following example:

C#
                        public
                         
                        interface
                         ICustomerModel
{
  
                        void
                         SetFullName([Required] 
                        string
                         firstName, [Required] 
                        string
                         lastName);
}
                        


                        public
                         
                        class
                         CustomerModel : ICustomerModel
{
  
                        public
                         
                        void
                         SetFullName(
                        string
                         firstName, 
                        string
                         lastName)
  {
     
                        this
                        .FullName = firstName + 
                        " "
                         + lastName;
  }

}
                      

Here ICustomerModel.SetFullName method specifies that the firstName and lastName parameters are required using the RequiredAttribute attribute. Since the CustomerModel.SetFullName method implements this method, these attributes will also be applied to its parameters.

Note Note

If the derived class exists in a separate assembly, that assembly must be processed by PostSharp and must reference PostSharp and PostSharp Model pattern assembly.