PostSharp. Overview.

Before turning directly to the theme of the story, it is necessary to say a few words about the system things.

Aspect-Oriented Programming

Aspect-oriented programming (AOP) - programming paradigm, based on the idea of separation of functionality to improve the partitioning the program into modules.

There are many classes of problems whose solution is impossible in the context of the OOP, or lead to a large rubbish code and connectivity modules that bad. For example, logging. In order to keep a log of the program, it is necessary in each service method of placing multiple lines of service call logging, as it may have to pass through the input parameters of methods. All this code would not apply to the implementation of real-world task entrusted to the method, but only an eyesore. Besides, how many extra lines of code have to write by hand!

Another example is the authentication and verification of access rights. In good, before the execution of important methods, one must each time test whether the current user rights to run the specified method. Here, too, can be a lot of hassle and code

In general, any cross-cutting code drops out of the opportunities the PLO. AOP programming, by contrast, provides all the tools to highlight “through the code in separate entities, which significantly simplifies the code for testing and for use.

Basic concepts of AOP:

  • Aspect – a module or class that implements cross-cutting functionality. Aspect modifies the behavior of the rest of the code, applying to the Board junction points identified some of the cut.
  • Advice – the decoration of the code, which must be called from the point of connection. Council may be executed before, after or instead of the junction.
  • Join point – point in the program you run, where to apply advice. Many implementations of AOP you can use method calls and appeals to the fields of the object as the connection points.
  • Paintcut – a set of connection points. The cut determines the suitability of this point of connection to this board. The most convenient implementation of AOP is used to determine the syntax of the main sections of the language and allow them to reuse by renaming and combining.
  • Introduction – restructuring of class and / or change the inheritance hierarchy to add functionality aspect of alien code. Usually implemented using some metaobject protocol.

Now we can go directly to the main theme of the narrative.

PostSharp

PostSharp – aspect-oriented framework, it introduces the aspect-oriented programming platform. Net. With PostSharp and AOP, you can identify the technical requirements of the individual entities (aspects).

  • Technical requirements are realized as a simple C # class
  • Aspects are applied to business objects without changing their source code.
  • During assembly, aspects are implemented in business objects.

The considered framework allows you to specify which types of data (class, assembly) to apply the aspects of how to implement inheritance issues and how they can interact with each other, order and many other nuances of use.

At the moment the official release is at version 1.5, version 2.0 is in CTP stage or already heavily RC. Basically it will be about 1.5, about 2.0 goodies I too will not forget and tell where it is required.

Key aspects

OnMethodBoundary

Aspect can be created by inheritance from the class OnMethodBoundaryAspect or interface IOnMethodBoundaryAspect.

This point applies when you have access to the source code of the method and you want to track events at the beginning of a method call, end call, the exception and successful conclusion. All this is done by overriding methods OnEntry, OnExit, OnException and OnSuccess respectively.
Schematically, the code after the application aspect will look like this (of course, it will be in the bins IL assembly)

int MyMethod(object arg0, int arg1) {
    OnEntry();
    try {
        // Original method body.
        OnSuccess();
        return returnValue;
    }
    catch ( Exception e ) {
        OnException();
    }
    finally {
        OnExit();
    }
}

In fact, everything looks more complicated, but to understand this is an excellent illustration. Object type MethodExecutionEventArgs transmitted to all 4 methods, and by using this site you can read and write values in the parameters passed, get current error message, override the return value and change during the procedure.

Access to parameters is carried out using methods GetReadOnlyArgumentArray () and GetWritableArgumentArray() class MethodExecutionEventArgs. Please note that change can only be those values that are passed by reference. By and large, both methods return the same set of objects, but in future versions of this behavior can change.

OnFieldAccess

Aspect can be created by inheritance from the class OnFieldAccessAspect or interface IOnFieldAccessAspect.

Application of this aspect allows to intercept all read/write operations for the field class. This aspect has 2 methods to override: OnGetValue and OnSetValue. Both of these methods are as a parameter class FieldAccessEventArgs, which has 2 properties of interest to us StoredValue and ExposedValue. The first allows access to the actual value in the field, while the latter acts as a buffer for reading there will be an object which will be returned, while recording, the object that came to record.

In other words, the default implementation for OnGetValue:

eventArgs.ExposedValue = eventArgs.StoredValue

And OnSetValue will be implemented as:

eventArgs.StoredValue = eventArgs.ExposedValue

More details about the mechanism of action of this aspect will be elsewhere.

OnMethodInvocation

Aspect can be created by inheritance from the class OnMethodInvocationAspect or interface IOnMethodInvocationAspect.
Just like the aspect OnMethodBoundary, this aspect allows you to add additional behavior to the method. The difference is that this aspect does not modify the body of the original method, but the intercepts and replaces it by yourself, or rather that it will be written in the method OnInvocation. This method takes as a parameter class MethodInvocationEventArgs and the most interesting is the method Proceed, which actually is the original method. Implementation of the method OnInvocation by default is already call Proceed, thus not worth once again call this method if you are using base.OnInvocation. And vice versa, respectively.

When dealing with this aspect may have access to the original method through the properties of Delegate. There’s also a way to get the parameters passed by calling a GetArgumentArray() method of class MethodInvocationEventArgs. The result is an array of objects that can be changed to your taste. The total value should be written in the property ReturnValue.

eventArgs.ReturnValue =  eventArgs.Delegate.DynamicInvoke( eventArgs.GetArgumentArray() );

OnException

Aspect can be created by inheritance from the class OnExceptionAspect or interface IOnExceptionAspect.

This aspect adds an exception handler in the method is applied to a dimension that allows you to enter the code exception handling in a separate attribute, rather than spreading it all the classes. In the method GetExceptionType() can determine what types of exceptions will be processed, if nothing to write, then the main handler will catch all exceptions. Himself an exception handler is in the method OnException(). That took exception will be available through a property Exception (read only) class MethodExecutionEventArgs. If you need to be replaced by an exception to any other, need to create a new exception. Ignoring exceptions is managed through ControlFlow.

ImplementMethod

Aspect can be created by inheritance from the class ImplementMethod or interface IImplementMethod.

Using this aspect you can divide declaration and implementation of abstract and extern methods.

When aspect was applied on method it’s no more abstract and get implementation that provided in the method OnExecution with parameters MethodExecutionEventArgs. MethodExecutionEventArgs allows you get access to the method body by property Method and get access to arguments GetWritableArgumentArray(). Output can be set by ReturnValue property.

Composition

With this aspect, it can introduce new interfaces to an existing type, and separate their implementation in other facilities. Composition types usually considered to be more good way to implement multiple inheritance.

More importantly, this aspect can be used to automatically implement interfaces, whose code generally repetitive and unremarkable. For example how to interface INotifyPropertyChanged.

More information about this aspect will be discussed in other articles, there can be many things to tell.

Example

Suppose you have a large and full-length project using multi-threading. All of a sudden began to emerge elusive bug that will not play on your machine with the debugger and you decide zalogirovat all accesses to the namespace System.Threading.

To start using PostSharp in your project, you need to add to a list of links of the project, two libraries PostSharp.Public.dll and  PostSharp.Laos.dll.
Since we will have logged methods are not of our assemblies, we will apply the aspect OnMethodInvocationAspect.

using System;
using PostSharp.Laos;

namespace PostSharp.Laos.Test {
    [Serializable]
    public class MyOnMethodInvocationAspect : OnMethodInvocationAspect {
        public override void OnInvocation(MethodInvocationEventArgs context) {
            Console.WriteLine("Calling {0}", context.Delegate.Method);
            context.Proceed();
        }
   }
}

Aspects should always be marked as serializable, it is necessary in the implementation of the code and paste in all the right places of the program, to the methods and classes to which you have applied aspect. Next, we overload a method in which OnInvocation and concludes the method name to the console.

Apply aspect can be as follows:

[assembly: MyOnMethodInvocationAspect( AttributeTargetAssemblies = "mscorlib", AttributeTargetTypes = "System.Threading.*")]

This line is written in the AssemblyInfo.cs file for your interest assembly. With this job you will not have to attribute dimension in a million places call functions associated with multithreading, the argument AttributeTargetTypes allows you to specify what aspect of use with regular expressions.

As a result PostSharp find all calls from the System.Threading namespace and replace them with the method call MyOnMethodInvocationAspect.Invoke. Naturally this will be a compile-time applications.

End of the First Part

In this article I talked about what aspects are and how they work in general. The following articles, I plan to elaborate on each of them. Tell how aspects can interact with each other, as they can be managed through the attributes, as their application can be validated at compile time. What new things have appeared in the second version of the framework.

Hard’n’heavy!

Tagged , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>