Open sandboxFocusImprove this doc

Accessing Members of the Target Class

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.

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:

    Member Kind Field Type
    Method A typed Delegate, typically one of the variants of Action or Func<TResult>. The delegate signature should exactly match the signature of the imported method.
    Property Property<TValue>, where the generic argument is the type of the property.
    Collection Indexer Property<TValue, TIndex>, where the first generic argument is the type of the property value and the second is the type of the index parameter. Indexers with more than one parameter are not supported.
    Event Event<TDelegate>, where the generic argument is the type of the event delegate (for instance EventHandler).
  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 (Get, Set; Add, Remove). These delegates can be invoked by the aspect as any delegate.

The property 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 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 important to process classes, aspects and advices in a consistent order.

PostSharp enforces the following order:

  • Base classes are processed first, derived classes after. Therefore, when a class is being processed, all parent classes have already been fully processed.

  • Aspects targeting the same class are sorted (see Coping with Several Aspects on the Same Target) and executed.

  • Advices of the same aspect are sorted and executed in the following order:

  • Member imports which have the property Order set to BeforeIntroductions.

  • Member introductions.

  • Members imports which have the property Order set to AfterIntroductions (this is the default value).

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

Advice Precondition Behavior
ImportMemberAttribute No member, or private member defined in a parent class. Error if IsRequired is true, ignored otherwise (by default).
Non-virtual member defined. Member imported.
Virtual member defined. If 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 OverrideAction is Ignore or OverrideOrIgnore, otherwise fail (by default).
Virtual member defined in a parent class Introduce a new override method if the property 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 OverrideAction is Fail.
Otherwise:
* 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.
* Override the method with the imported method.

See Also

Reference

IntroduceMemberAttribute
ImportMemberAttribute
Other Resources

Coping with Several Aspects on the Same Target