The purpose of Aspect# language is to offer you a cleaner way to configure, describe and document your aspects configuration without have to rely on creepy xml syntax to do so.
Table of contents
- Basic definitions
- Imports
- Global Interceptors
- Global Mixins
- Aspects
- Includes
- Pointcuts
- Advices
Basic definitions
You must obey to a few rules to use the Aspect# language, and the first rule is that order matters. So your declarations must obey this sequence:
[Imports]
[Global Interceptor map]
[Global Mixin map]
Aspects definitions
Imports
The imports section helps you to keep a clean code and helps the language to resolve the types.
Import Namespace.Name [in AssemblyName]
Examples:
Import System.Collections in System
Import AspectSharp.Core
Global Interceptors
In the case that you have an interceptor that is going to be used in more than one aspect - or even more than one pointcut, you can define it in an global interceptor section:
interceptors [
"key" :InterceptorType ;
"key2" : InterceptorType2
]
Examples
interceptors [
"logger" : DigitalGravity.Interceptors.Logger in DigitalGravity.XProject
]
Import DigitalGravity.Interceptors in DigitalGravity.XProject
interceptors [
"logger" : Logger
]
Once you've done it, you can refer to them in an aspect declaration by their keys:
aspect Test for MyClass
pointcut method(*y)
advice("key")
end
pointcut property(*y)
advice("key2")
end
end
Global Mixins
For the same reason there is also a mixin global section:
mixins [
"key" : MixinType ;
"key2" : MixinType2
]
Examples
mixins [
"security" : DigitalGravity.Mixins.SecurityMixin in DigitalGravity.XProject
]
Import DigitalGravity.Mixins in DigitalGravity.XProject
mixins [
"security" : SecurityMixin
]
Once you've done it, you can refer to them in an aspect declaration by their keys:
aspect Test for MyClass
include("security")
end
Aspects
An aspect section defines which mixins and which pointcuts will be applied to a type or a set of types:
aspect Name for Type
[include]
[pointcuts]
end
Examples
aspect MyAspect for Customer
end
aspect MyAspect for [ My.Namespace.Classes excludes(Customer,Author) ]
end
aspect MyAspect for [ assignableFrom(Customer) ]
end
aspect MyAspect for [ customMatcher(MyAspectMatcher) ]
end
When you invoke the AspectEngine.Wrap method on an instance, basically Aspect# will try to match the aspects for that particular instance. If more than one are matched, a new aspect is created from the union and will be used as the aspect definition.
If you need a more specific semantic to match aspects, you can provide your own using the customMatcher keyword (as the example above). Your class must implement the IClassMatcher interface and perform its logic returning true if the instance is eligible for that aspect.
Includes
You use one or more include to add mixins to the resulting type in an aspect definition.
Examples
aspect MyAspect for Customer
include DigitalGravity.Mixins.Security in DigitalGravity.XProject
include System.Collections.ArrayList in System
end
Pointcuts
The purpose of pointcuts is to define an expression that must be true (matched) in order to introduce advices.
pointcut [target][method signature]
advice(type)
advice("key")
end
The possible targets are:
- method
- property
- propertyread
- propertywrite
You can also combine them if you want, provided that they make sense
pointcut method|property(*)
end
pointcut method|propertyread(*)
end
pointcut propertywrite(*)
end
Using property|propertywrite for instance is meaningless, and you'll get an error.
The method signature can be simple as a
meaning everything, or (System.IList Create(int, *)) meaning methods named Create that returns System.IList and have at least the first argument of the type int. Please note that return types and argument types here are not resolved, so you have to use the full type name.
Regular expressions are not fully supported. In fact, you can use only .* to match something in the rest of an name like (Str.* Create(int, string)) that will match Create methods with two arguments (the first an int and the second a String) and returning a type which the name starts with Str, like String, Strange, Stripissimo and so on.
Examples
pointcut property(* Name)
end
pointcut property(string C.*Name)
end
pointcut method(void Perform)
end
pointcut method(void Perform(string, *))
end
Advices
Advices are the pieces of code that will be associated with a given joinpoint. Aspect# only supports MethodInterceptors advices.
Please note that we use lazy instantiation of interceptors and only one instance of an interceptor will exist per Wrap(). In other words, proxies will not share interceptors.
Examples
aspect MyAspect for Customer
pointcut method(*)
advice(LogInvocationInterceptor)
end
end
aspect MyAspect for Customer
pointcut method(*)
advice(Namespace.MyLogger in MyAssembly)
end
end
(transfered from wiki.castleproject.org)