Custom attribute that, when applied to an instance field of an aspect class, determines that this field should be bound to a method, event or property of the target class of this aspect. Valid types for fields are a concrete Delegate (to bind to a method), Property<TValue> or Property<TValue, TIndex> (to bind to a property), or Event<TDelegate> (to bind to an event). When applied to a parameter of an advice method, determines that the parameter receives a field, a property or a method of the target class.
Namespace: PostSharp.Aspects.Advices
Assembly: PostSharp.dll
Syntax
[AttributeUsage(AttributeTargets.Field|AttributeTargets.Parameter, AllowMultiple = false)]
public sealed class ImportMemberAttribute : AdviceRemarks
On an advice parameter. The advice receives a field or a property of the target class, in any aspect, including a statically scoped aspect. The type and the mode of the parameter select what the advice receives:
- A parameter of the type of a field, passed by value, as
in,reforout, receives the field: a copy of its value, or a reference to the field. Areforoutparameter requires a field that is not read-only. - A parameter of the type of a property, passed by value or as
in, receives the value that the getter returns when the advice is called. A property that returns a reference (ref T) is a location, as a field is: a parameter passed asin,reforoutreceives the reference, andreforoutrequires a reference that is not read-only. - A parameter of type ILocationBinding<T> or ILocationBinding receives the binding of the field or property, which reads and writes it on the object passed to its methods, typically received by a ThisAttribute parameter. There is one binding object per member and target type.
- A parameter of a delegate type, with a member name, receives an open delegate of a method: the first parameter of the delegate
receives the object of an instance method, and the other parameters are the parameters of the method. For a struct, the first parameter
is
inorref, with a custom delegate type:infor any method, andrefonly for a method that is notreadonly. Throughin, a method that is notreadonlyis called on a copy of the struct, as in C#. The method is converted as C# converts a method group to a delegate type: by identity or reference conversions, without boxing, and the signature of the delegate selects the overload. A virtual method is dispatched on the object. The delegate is created once per target type, so calling the method does not allocate. - A parameter of type IMethodBinding receives the binding of a method, which calls it on the object passed to Invoke(ref object, Arguments), with the arguments of an Arguments object. The name selects the method, so a method with overloads must be imported as a delegate.
- A parameter of type IEventBinding, with a member name, receives the binding of an event, which adds and removes handlers of the event on the object passed to its methods, and invokes a handler with the arguments of an Arguments object.
- In an instance advice of an instance-scoped aspect (IInstanceScopedAspect), a parameter of type Property<TValue> or Event<TDelegate> receives an object bound to the target object, created once per target object, as an aspect field of these types receives.
With member names, the member is selected by name, in the order of the names, among the members whose type the parameter accepts. Without a name, the member is selected by type, as ArgumentAttribute selects an argument: a parameter passed by value accepts a member whose type is assignable to it without conversion, except boxing, and a parameter passed by reference or a location binding requires the exact type. When several members match, the build fails. The members of the target class and the accessible members of its base classes are candidates, but not indexers. A method is always selected by name.
The fields that the aspect instance requests with IntroduceFieldAdviceInstance win over the members of the target class: with names, a field requested under a name is selected before a member that has this name; without a name, the requested fields whose type the parameter accepts are the only candidates. The fields requested by other aspects are members of the target class, under their real names.
When no member matches, the parameter receives null, the default value, or a reference to a temporary variable, unless
IsRequired is true, which is then a build error. On a static target, a parameter passed by value receives the default value
of an instance member.
When another aspect turns a field into a property, such as a LocationInterceptionAspect, the order of the aspects decides
what the parameter sees, as it decides for any two aspects. An aspect ordered before the other aspect sees the field itself, and
an aspect ordered after it sees the property: its values go through the accessors, and it cannot be passed as ref or out.
Declare the order with AspectTypeDependencyAttribute or another aspect dependency.
For a method, a property or an event imported as a delegate, an IMethodBinding, a Property<TValue> or an Event<TDelegate>, Order has the meaning that it has on an aspect field: with BeforeIntroductions, the parameter calls the method as it was before the aspect introduced or overrode it, without virtual dispatch.
On an aspect field.
Fields annotated with the ImportMemberAttribute custom attribute must be public and must not be read-only.
At runtime, these fields are assigned to a delegate (in case of method binding) or a pair of delegates (in case of event or property binding) that can be used to invoke the imported member.
When the IsRequired property is set to true and the target type does not contain a member of the required
name and signature, a build error is raised.
When multiple member names are specified, the first existing member satisfying all conditions is used.
When the same aspect also introduces or overrides the member, Order determines whether the field is bound to the member as it was before or after the introductions of the aspect.
The fields are bound when the aspects of the target object are initialized, normally in the constructor. When objects are created without calling a constructor, for example by a custom deserializer, initialize the aspects manually as described in Coping with Custom Object Serializers.
To choose the imported members at build time, or to import several fields or properties into a single aspect field, implement IAdviceProvider and return ImportLocationAdviceInstance or ImportMethodAdviceInstance objects instead.
Constructors
| Name | Description |
|---|---|
| ImportMemberAttribute(string) | Initializes a new instance of the ImportMemberAttribute class and specifies a single name for the member to import. |
| ImportMemberAttribute(params string[]) | Initializes a new instance of the ImportMemberAttribute class and specifies several possible names for the member to import. |
Properties
| Name | Description |
|---|---|
| IsRequired | Gets or sets a value indicating whether a build-time error must be issued if the member to be
imported is absent. If |
| MemberNames | Gets the possible names of the imported member, in order of precedence. When the array is empty, the member imported into an advice parameter is selected by its type. |
| Order | Gets or sets the moment when the member should be imported: either before (BeforeIntroductions) or after (AfterIntroductions) members have been introduced by the current aspect. The default is AfterIntroductions. |