Skip to main content

AOP and PostSharp

In the last weeks we discover together the base principles of Aspect Oriented Programing (AOP). Now is the time to see how we can use at real power the AOP characteristics using PostSharp.
AOP
Before going straight to subject let’s make a short recap. AOP is a programming paradigm with the main goal of increasing modularity of an application. AOP tries to achieve this goal by allowing separation of cross-cutting concerns – using interception of different commands or requests.
In the last posts we discover how we can use AOP using Unity and .NET 4.5 features (RealProxy). Unity give us the possibility to register action that can be executed before and after a specific action. The RealProxy class is the base class around all this features that it is used by frameworks like Unity to offer this feature.
 The biggest different between RealProxy and a stack that offers us AOP is from the features perspective. Using RealProxy directly will require us to write all the functionality that we need – this can be translated to time, money and more code that we need to maintain (in the end we don’t want to reinvent the wheel.

PostSharp
PostSharp is the first real AOP framework presented in this series of articles. Until now we looked on different ways how we can use AOP features, but without using a real and dedicated AOP stack.
I decided to start with PostSharp, because when you need an AOP framework for a real projects , that is pretty big and complex you should look at PostSharp first. If is the kind of framework that offers you almost all the features of AOP that you would need.
Usually I compare PostSharp with ReSharper from the quality of the product. It is the kind of product that has all the features that you need when you talk about a specific feature.
PostSharp has a lot of features that cannot be discussed in only one article. In the near feature we will study each of this feature separately, but for now we will look around the most important features that are around AOP.
Features
The main features of PostSharp are:
  1. Threading Pattern Library - Allow us to control the level of abstraction around threading, detect and diagnosed deadlocks, control how action are executed on different threads and position (foreground or background)
  2. Model Pattern Library – Offers us the full features of AOP using INotifyPropertyChanged interface. All the setup and other things will be taken care by PostSharp. More complicated behavior can be implemented very simple when we start to use Code Contracts
  3. Architecture Framework – Give us the power to validate different aspect of code quality and design, design patterns, core relationships, code analysis and many more

We saw what are the main features of PostSharp, now let’s inspect the technical part and see how we can add AOP in our project using PostSharp.
How does it works
The biggest difference between PostSharp and other AOP solutions is how the custom behavior is added. In general this behavior is added at runtime, but not in the case of PostSharp. All the hooks are added at compile time. In this way the performance is not affected too much. Of course any AOP framework, the performance if affected a little, but in PostSharp case, the performance is almost the same as without it.

Basically, PostSharp has a post-processor action, that takes the code that is compiled and modify it. All the hooks are added at this level. The output from compiler is taken by PostSharp and cooked.
Before and After a call
The most common use case when AOP is used is to execute a specific action before and after a method of property is called (for example for logging). This can be done very simple using PostSharp with a few lines of code.
First step is to define the behavior that we want to execute in that specific moment. This can be accomplished by extending OnMethodBoundaryAspect. We can override OnEntry, OnSuccess and OnException. In each of this method we have access to input parameters, to the result and so on. We can even change the result of the call.
[Serializable]
public class FooAOPAttribute : OnMethodBoundaryAspect
{    
    public override void OnEntry(MethodExecutionArgs args)
    {
        ...
    }
   
    public override void OnSuccess(MethodExecutionArgs args)
    {
    ...
    }
  
    public override void OnException(MethodExecutionArgs args)
    {
    ...
    }
}
From this moment we can use this attribute to annotate all the method for which we want to have this feature. Of course we can specify the list of methods not only in this way. We can specify the list of method from AssemblyInfo.cs, where we can define custom filters for which methods we would like to have this feature.
Code Injection
This feature allow us to add code to our class at runtime. Using a custom attribute or from AssemblyInfo.cs we can inject specific code to our class. For example we can specify that a class implemented a specific interface or inject a specific method of property.
In the below example we can discover how we can inject a specific property to our class:
[Serializable]
public class FooAOPAspect : InstanceLevelAspect
{
    public string FirstName { get; set; }
}

[IntroduceMember]
public string FirstName { get; set; }

[FooAOPAspect]
public class Student
{

}
The IL code that will be generated will contains the FirstName property inside.
INotifyPropertyChange
When we are working on a desktop or native application, we need to use this interface to be able to receive notification when the value of property is changed (on UI or in code). Usually this is made by implementing the above interface. To not over complicate the code, a base class is created when the notification functionality is added.
For a small code this is acceptable, but if you have a complicated application you would add a lot of duplicate code to support this feature.
This problem is resolved by PostSharp for us by NotifyPropertyChangedAttribute. Once we add this property to our class through Smart Tag we will not need any more to care about notifications. PostSharp will take care about the rest.
[NotifyPropertyChanged]
public class StudentEdit
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string FullName
    {
        get
    {
      return FirstName + LastName);
    }
    }  
    public string Email { get; set; }
}
One thing that I liked was the Transitive Dependencies support. This mean that if FirstName value is changed, a notification will be triggered for FullName also.
If we want to add a specific attribute to all our classes from a namespace we can do this pretty simple using attribute multicasting. This is done directly in AssemblyInfo.cs file and will allow us to specify for which classes we need to add a specific attribute. We have the possibility to add filters, exclude specific class and so on. Of course this multicasting setup can be done directly from code using IAspectProvider.
The last thing that you should know about this is that you also have other attributes that can be used to ignore specific property or handling notification in a custom way.
Code Contracts
As the name is telling us, Code Contracts give us the possibility to define a contracts at code level between the called and method of property that is called. In this way the input validation will not needed to be made with a custom IF anymore. It is pretty similar with the custom validation that can be made through ActionFilter and validation attributes in MVC for example. The advantage is that we can define this contract at any level, for example  when we are exposing a library API.
The most simple example if NULL checks. Usually when we need to do a NULL check we add an IF in our method/property and throw an exception when value is not NULL. The same thing can be done if we are using the Required attribute.
See below example:
public class Student
{
  public void SetLastName([Required] string newLastName)
  {
    ...
  }
}
Without PostSharp we would need to check in the body of the message the value of input and throw an exception. Imagine writing the same code for 1.000 times. This kind of attributes can be used also at property or field level. One interesting thing is when we are using it ad field value. When we set this value at field or property value it is not important from where the value is set (for example from another method), the check for NULL will be made.
public class Student
{
  [Required]
  private string _lastName = "Default"

  public void SetLastName(string newLastName)
  {
    _lastName = newLastName;
  }
  
  public string LastName
  {
    get { return _lastName; }
    set { _lastName = value; }
  }

  public void SetFullName(string newFullName)
  {
    ...
    _lastName = lastName;
  }
}
Cool :-)
A part of default validation action are already define. Anytime we can define our own custom validation by implementing ILocationValidationAspect. We have ValidateValue method that we need to implement where we can do our custom validation.
Other features
There are other great features that we didn’t discussed yet, from the one that allow us to intercept events, composite aspect, code injection, exception handling, security, object persistence and many more. Another feature that I like at PostSharp is the ability to specify that an interface cannot be implemented by other assemblies and can be only used.
I invite all of you to visit PostSharp web site and try it.
Licensing and Costs
There are 3 type of licensing of PostSharp. For individual use you can use with success the Express version that is great when you want to learn and understand how does PostSharp works.
Additional to Express one we have Professional and  Ultimate that comes with other features that can be used with success in production.
Don’t forget that the licensing model is per developer not per products developed. This means that you can use the same license for 1 or 100 projects.
Conclusion
Of course all this feature can be implemented by us, but PostSharp offers all this things out of the box. This is a great AOP stack used worldwide, extremely mature and good.

Comments

Popular posts from this blog

Windows Docker Containers can make WIN32 API calls, use COM and ASP.NET WebForms

After the last post , I received two interesting questions related to Docker and Windows. People were interested if we do Win32 API calls from a Docker container and if there is support for COM. WIN32 Support To test calls to WIN32 API, let’s try to populate SYSTEM_INFO class. [StructLayout(LayoutKind.Sequential)] public struct SYSTEM_INFO { public uint dwOemId; public uint dwPageSize; public uint lpMinimumApplicationAddress; public uint lpMaximumApplicationAddress; public uint dwActiveProcessorMask; public uint dwNumberOfProcessors; public uint dwProcessorType; public uint dwAllocationGranularity; public uint dwProcessorLevel; public uint dwProcessorRevision; } ... [DllImport("kernel32")] static extern void GetSystemInfo(ref SYSTEM_INFO pSI); ... SYSTEM_INFO pSI = new SYSTEM_INFO(...

ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded

Today blog post will be started with the following error when running DB tests on the CI machine: threw exception: System.InvalidOperationException: The Entity Framework provider type 'System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer' registered in the application config file for the ADO.NET provider with invariant name 'System.Data.SqlClient' could not be loaded. Make sure that the assembly-qualified name is used and that the assembly is available to the running application. See http://go.microsoft.com/fwlink/?LinkId=260882 for more information. at System.Data.Entity.Infrastructure.DependencyResolution.ProviderServicesFactory.GetInstance(String providerTypeName, String providerInvariantName) This error happened only on the Continuous Integration machine. On the devs machines, everything has fine. The classic problem – on my machine it’s working. The CI has the following configuration: TeamCity .NET 4.51 EF 6.0.2 VS2013 It see...

Navigating Cloud Strategy after Azure Central US Region Outage

 Looking back, July 19, 2024, was challenging for customers using Microsoft Azure or Windows machines. Two major outages affected customers using CrowdStrike Falcon or Microsoft Azure computation resources in the Central US. These two outages affected many people and put many businesses on pause for a few hours or even days. The overlap of these two issues was a nightmare for travellers. In addition to blue screens in the airport terminals, they could not get additional information from the airport website, airline personnel, or the support line because they were affected by the outage in the Central US region or the CrowdStrike outage.   But what happened in reality? A faulty CrowdStrike update affected Windows computers globally, from airports and healthcare to small businesses, affecting over 8.5m computers. Even if the Falson Sensor software defect was identified and a fix deployed shortly after, the recovery took longer. In parallel with CrowdStrike, Microsoft provi...