Transforming code: concepts
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.
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.
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 advice is added by implementing the BuildAspect method, thanks to the methods exposed by the Advice property of the
builder parameter. Refer to IAdviceFactory for a complete list of methods. In brief:
- Override allows you to replace the implementation of a type member.
- 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.
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.