Accessing Members of the Target ClassPostSharp Documentation

PostSharp makes it possible to import a delegate of a target class method, property or event into the aspect class, so that the aspect can invoke this member.

These mechanisms allow developers to encapsulate more design patterns using aspects.

This topic contains the following sections.

Importing Members of the Target Class

Importing a member into an aspect allows this aspect to invoke the member. An aspect can import methods, properties, or fields.

To import a member of the target type into the aspect class:

  1. Define a field into the aspect class, of the following type:

  2. Make this field public. The field cannot be static.

  3. Add the custom attribute ImportMemberAttribute to the field. As the constructor argument, pass the name of the member to be imported.

At runtime, the field is set to a delegate of the imported member. Properties and events are imported as set of delegates (Property TValue  Get, Property TValue  Set; Event TDelegate  Add, Event TDelegate  Remove). These delegates can be invoked by the aspect as any delegate.

The property ImportMemberAttribute IsRequired determines what happens if the member could not be found in the target class or in its parent. By default, the field will simply have the null value if it could not be bound to a member. If the property IsRequired is set to true, a compile-time error will be emitted.

Interactions Between Several Member Introductions and Imports

Although member introduction and import may seem simple advices at first sight, things become more complex when the several advices try to introduce or import the same member. PostSharp handles these situations in a robust and predictable way. For this purpose, it is primordial to process classes, aspects and advices in a consistent order.

PostSharp enforces the following order:

  1. Base classes are processed first, derived classes after. Therefore, when a class is being processed, all parent classes have already been fully processed.
  2. Aspects targeting the same class are sorted (see Coping with Several Aspects on the Same Target) and executed.
  3. Advices of the same aspect are sorted and executed in the following order:

    1. Member imports which have the property ImportMemberAttribute Order set to BeforeIntroductions.
    2. Member introductions.
    3. Members imports which have the property ImportMemberAttribute Order set to AfterIntroductions (this is the default value).

Based on this well-defined order, the advices behave as follow:

AdvicePreconditionBehavior
ImportMemberAttribute No member, or private member defined in a parent class. Error if ImportMemberAttribute IsRequired is true, ignored otherwise (by default).
Non-virtual member defined. Member imported.
Virtual member defined. If ImportMemberAttribute Order is BeforeIntroductions, the overridden member is imported. This similar to calling a method with the base prefix in C#. Otherwise (and by default), the member is dynamically resolved using the virtual table of the target object.
IntroduceMemberAttribute No member, or private member defined in a parent class. Member introduced.
Non-virtual member defined in a parent class Ignored if the property IntroduceMemberAttribute OverrideAction is Ignore or OverrideOrIgnore, otherwise fail (by default).
Virtual member defined in a parent class Introduce a new override method if the property IntroduceMemberAttribute OverrideAction is OverrideOrFail or OverrideOrIgnore, ignore if the property is Ignore, otherwise fail (by default).

Member defined in the target class (virtual or not)

Fail by default or if the property IntroduceMemberAttribute OverrideAction is Fail.

Otherwise:

  1. Move the previous method body to a new method so that the previous implementation can be imported by advices ImportMemberAttribute with the property Order set to BeforeIntroductions.
  2. Override the method with the imported method.
Examples

Example: Raising an Event When the Object is Finalized

See Also

Reference