Overview

In .NET, you normally need to write one line of code for any application of a target attributes. If a custom attribute applies to all types of a namespace, you have to manually add the custom attribute to every single type.

By contrast, multicast custom attributes allow you to apply a custom attributes on multiple declarations by using wildcard or regular expressions, or by filtering on some attributes. It makes it easy to apply an aspect to, say, all public static methods of a namespace, with a single line of code.

Custom attributes supporting multicasting needs to be derived from MulticastAttribute. All PostSharp Laos aspects are derived from this class.

Note. Custom attribute multicasting is a feature of PostSharp. If you do not transform your assembly using PostSharp, multicast attributes will behave as plain old custom attributes.

Behavior of a multicast attribute

Multicast custom attributes have a set of valid targets: types, methods, fields, properties, or events.  For instance, a caching aspect targets methods. A field validation aspect targets fields.

When a field-level multicast attribute is applied to a type, the attribute is implicitly applied to all fields of that type. When it is applied on an assembly, it is implicitly applied to all fields of that assembly.

The general rule is: when a multicast attribute is applied on a container, it is implicitly (and recursively) applied to all elements of that container.

The next table illustrates how this rule translates for different kinds of targets.

Directly applied to Implicitly applied to
Assembly or Module Types, methods, fields, properties, and events contained in this assembly or module.
Type Methods, fields, properties, and events contained in this type.
Property or Event Accessors of this property or event.
Method This method.
Field This field.

Note that the default behavior is maximalist: we apply the attribute to all contained elements. However, PostSharp provides a way to restrict the set of elements to which the attribute is multicast: filtering.

Both the attribute developer and the attribute user can specify filters.

Multicasting filters specified by the attribute developer

Just like normal custom attributes should be decorated with the [AttributeUsage] custom attribute, multicast custom attributes must be decorated by the [MulticastAttributeUsage] attribute (see MulticastAttributeUsageAttribute). It specifies which are the valid targets of the multicast attributes.

For instance, the following piece of code specifies that the attribute OnMethodBoundaryAspect, and all attributes derived from it, apply on methods or constructors that are not abstract and are implemented in managed code:

[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | 
                AttributeTargets.Constructor | AttributeTargets.Event | 
                AttributeTargets.Method | AttributeTargets.Property | 
                AttributeTargets.Struct,
                AllowMultiple = true, Inherited = false)]
[MulticastAttributeUsage( MulticastTargets.Method | MulticastTargets.Constructor, 
                          AllowMultiple=true,
                          TargetMemberAttributes = 
                            MulticastAttributes.NonAbstract | 
                            MulticastAttributes.Managed)]
public abstract class OnMethodBoundaryAspect ...

Note, in the sample above, the presence of the AttributeUsage attribute. It tells the C# or Visual Basic compiler that the attribute can be directly applied to assemblies, classes, constructors, methods, and so on. But this aspect will never be finally applied to an assembly or a class. Indeed, the MulticastAttributeUsageAttribute attribute specifies that the sole valid targets are methods and constructors. Furthermore, the TargetMemberAttributes property establishes a filter that includes only non abstract methods written in managed code.

Therefore, if the aspect is applied on a type containing an abstract method, the aspect will not be multicast to this method.

The following table lists the filters available to the attribute developers:

Filtering Property Description
ValidOn Restricts the kinds of targets (assemblies, classes, value types, delegates, interfaces, properties, events, properties, methods, constructors) to which the attribute can be indirectly applied.
TargetTypeAttributes Restricts the visibility of the type to which the aspect is applied, or of the type declaring the member to which the aspect is applied.
TargetMemberAttributes Restricts the attributes (visibility, virtuality, abstraction, literality, ...) of the member to which the aspect is applied.
AllowExternalAssemblies Determines whether the attribute can be applied to elements defined in a different assembly than the current one.

Multicasting filters specified by the attribute user

The attribute user can specify multicasting filters using specific properties of the MulticastAttribute class. To make it clear that these properties only impact the multicasting process, they have the prefix Attribute.

The following table lists the filters available to the attribute developers:

Filtering Property Description
AttributeTargetElements Restricts the kinds of targets (assemblies, classes, value types, delegates, interfaces, properties, events, properties, methods, constructors) to which the attribute can be indirectly applied.
AttributeTargetTypes Wildcard expression or regular expression filtering by name the type to which the attribute is applied, or the declaring type of the member to which the attribute is applied.
AttributeTargetTypeAttributes Restricts the visibility of the type to which the aspect is applied, or of the type declaring the member to which the aspect is applied.
AttributeTargetMembers Wildcard expression or regular expression filtering by name the member to which the attribute is applied.
AttributeTargetMemberAttributes Restricts the attributes (visibility, virtuality, abstraction, literality, ...) of the member to which the aspect is applied.
AttributeTargetAssemblies Wildcard expression or regular expression specifying to which assemblies the attribute is multicast.

Inheritance of filtering attributes

Suppose we have two classes A and B, B being derived from A. Both A and B can be decorated with the [MulticastAttributeUsage]. However, since B is derived from A, filters on B cannot be more permissive than filters on A.

In other words, the [MulticastAttributeUsage] custom attribute is inherited. It can be overwritten in derived classes, but derived class cannot enlarge the set of possible targets. They can only restrict it.

Similarly (and hopefully predictably), the attribute user is subject to the same rule: she can restrict the set of possible targets supported by the aspect, but cannot enlarge it.

See also

Multiple Instances on the Same Target
Persisting Custom Attributes Metadata