Aspects can transform the target code by providing advice. Advice refers to a primitive transformation of code. It is safely composable, meaning that several aspects, even without knowledge of each other, can add advice to the same declaration.
Note
In English, the word advice is uncountable, i.e., grammatically plural. The grammatically correct singular form of advice is piece of advice, but using these words in a software engineering text seems unusual. In aspect-oriented programming, advice is a countable concept. Despite the challenges associated with using uncountable nouns as countable, we sometimes use an advice for the singular form and advices for the plural form, which may be occasionally surprising to some native English speakers. We use other neutral turns of phrases whenever possible unless it would make the phrase much more cumbersome or less understandable.
There are two methods to add advice: declaratively and imperatively.
Declarative advising
The only declarative advice is the member introduction advice, denoted by the IntroduceAttribute custom attribute. For each member of the aspect class annotated with [Introduce]
, the aspect framework will attempt to introduce the member in the target class. For details, refer to Introducing members.
Imperative advising
Imperative advice is added by implementing the BuildAspect method, thanks to the advising extension methods exposed by the builder
parameter implementing the IAdviser<T> interface.
The following methods are available:
- Override allows you to replace the implementation of a method, field, property, event, or constructor.
- IntroduceMethod, IntroduceProperty, IntroduceField, and IntroduceEvent enable your aspect to introduce new members into the target type. Refer to Introducing members for details.
- ImplementInterface allows the target type to implement an interface. Refer to Implementing interfaces for details.
- IntroduceAttribute and RemoveAttributes allow adding and removing custom attributes. See Adding custom attributes for details.
- AddContract allows you to add a pre-condition or post-condition to a field, property, or parameter. See Validating parameter, field, and property values with contracts for details.
- AddInitializer allows you to add an initialization statement in the constructor or static constructor. See Adding initializers for details.
- IntroduceParameter allows you to append a parameter to a constructor and pull them from constructors of derived classes. See Introducing constructor parameters for details.
Please refer to the AdviserExtensions class for a complete list of methods.
To advise a member of the current declaration (for instance, to override a method in the current type), you can get an adviser for the member by calling the IAdviser.With method.
Note
You can only advise the target of the current aspect instance or any declaration contained in this target. For instance, the BuildAspect
method of a type-level aspect can advise all methods of the current type, including all parameters.
Template methods
With most types of advice, you must provide a template of the member you want to add to the target type.
Templates are written in standard C# code but combine two kinds of code: compile-time and run-time. When some target code is advised, the compile-time part of the corresponding template is executed. The output of this execution is the run-time code, which is then injected into the source code to form the transformed code.
For details, refer to Writing T# templates.