A great feature of PostSharp is the ability to apply an aspect to multiple methods with a single declaration. This is called attribute multicasting and is explained in the PostSharp documentation.
Using multicasting you can add a single line to your assembly or module (such as in the AssemblyInfo.cs file) and have it apply to all classes in the assembly. For example, you could apply the GException aspect to record thrown exceptions throughout your assembly with just one line of code:
Multicasting GException to all methods in an assembly |
Copy Code
|
---|---|
// Log thrown exceptions for every method in this assembly.
[assembly: GException]
|
In many cases you won't quite want to apply an attribute to every single method in your assembly. To selectively restrict how the attribute is applied you can use the AttributeExclude feature of multicasting, along with AttributePriority like this:
Multicasting GTrace throughout an assembly |
Copy Code
|
---|---|
// Log entry and exit of every method with exceptions listed below [assembly: GTrace(AttributePriority = -1)] // Exclude constructors and a few excessively noisy classes & methods [assembly: GTrace(AttributeTargetMembers = ".ctor", AttributeExclude = true)] [assembly: GTrace(AttributeTargetMembers = "ToString", AttributeExclude = true)] |
When using multicasting a common pattern is to first apply an attribute broadly, then to refine it with a list of exclusions. In this scenario it is important that the broad declaration have lower priority than the exclusions because there is no order preserved in these statements so PostSharp has to have a way of knowing what applies first. As soon as it finds a match with a higher priority it stops looking for matches with lower priorities.
There are a lot of options for narrowing down how multicasting is applied. Keep in mind that in the same attribute you can also set common options for the Loupe aspects (like changing a category or disabling parameter logging). For full information see the PostSharp documentation.
If you are initializing Loupe programmatically (i.e. by subscribing to the Log.Initializing event), then be sure that you do not apply any Loupe aspects (or another aspect that would access Loupe) to any of the methods that are called in the flow of control leading up to the line in which you subscribe to the Initializing event. For example, if you subscribe to the event in Program.Main, be sure not to apply any Loupe aspects to this method. If you do, then Loupe will already be initialized (probably not the way you want) before you get a chance to subscribe.
Keep in mind that if you are using attribute multicasting (see above) you may be getting an aspect associated with your main routine even though it isn't there explicitly.
Be aware that PostSharp has known limitations working with obfuscated assemblies:
If you find that you want something not already covered by the Loupe Agent for PostSharp you should first try extending the closest Loupe aspect through inheritance. If that doesn't produce the effect you're looking for you can create your own aspects. A few notes:
There are other aspects that are built into PostSharp. For more information see the PostSharp Documentation.