AOP on .NET
These pages are about Aspect-Oriented Programming (AOP) techniques
for the .NET Framework. They help you understand what all is AOP and how AOP
is implemented on .NET. It is PostSharp-centric, but not limited to
PostSharp. We always try to refer to other existing AOP tools when relevant.
Aspect-Oriented Programming (AOP), also named
Aspect-Oriented Software Development (AOSD), is an
approach to software development that goes further in the direction of
separation of concerns. Separation of concerns is one of
the most important rules in software development. It states that the same
concern should be solved in a single unit of code. This is also called
modularization. In procedural programming, the unit of code
is the procedure (or function, or method). In object-oriented
programming, the unit of code is the class.
Some concerns cannot be implemented successfully using a pure procedural
or object-oriented programming. An example is code security. If you want
to secure objects and methods, you have to modify the code of each method.
That's why security is said a crosscutting concern,
because it crosscuts the unit of modularization of the programming
paradigm, in this case the class.
An aspect is a concern that cross-cuts many classes and/or
methods.
So AOP is a technique that allows to address issues that
cross-cuts objects. AOP is frequently used to implement caching, tracing,
security or failure injections.
See also our Glossary
for technical terms.
Say we have a large set of business objects and some of their methods
need to be secured. The current user is required to be in some roles in
order to be given the permission to execute the method. Using the AOP
programming model, you could, instead of modifying each method, develop
an aspect and 'apply' it on methods of interest. In PostSharp Laos, the
aspect could look like this:
public sealed class RequiresRoleAttribute : OnMethodBoundaryAspect
{
string[] roles;
public string[] Roles
{
get { return this.roles; }
set { this.roles = value; }
}
public override void OnEntry( MethodExecutionEventArgs e )
{
((ISecurable) e.Instance).RequireRoles( this.roles );
}
}
This defines a custom attribute that can be applied to any method. You
can use wildcards to apply the aspect to a set of objects and methods:
[assembly: RequiresRole(
Roles=new string[] { "Delete" }, TargetMethods="Delete*" )]
There are of course a lot of AOP techniques to achieve the same result.
The illustration above is only one of them.
There are basically two approaches to change the behavior of a program in
.NET (i.e. to weave a .NET program):
-
Compile-Time Weaving: the program is modified during the build process
on the development machine, before deployment.
- Runtime
Weaving: the program is modified during its execution, after
deployment.
We know what we want: apply additional behaviors to existing
code. Now we need to know how to express it. We have to express
the following facts:
- What behavior we want to add (advices),
- Where we want to add it (specification of join
points using pointcuts).
The following approaches are available when the .NET Framework is
targeted:
-
Extending the Language : Create a new .NET language with new
constructs.
- Companion
Files : Use external files, for instance XML files.
- Custom
Attributes : Use 'normal' .NET custom attributes to annotate the code.
- Domain-Specific Languages:
Use of a graphical designer to express the semantics, as well as IDE
integration to simplify build and debugging experiences
-
Programmatic Tipping : All previous approaches were declarative.
Another solution is to have normal .NET imperative code to add advices to
join points.