During compilation, PostSharp takes great care in making sure that everything works correctly. When something goes wrong, PostSharp will report it as an error or a warning. Until now, however, whenever an error or a warning occurred, the developer had to manually navigate to that place in code.

We are excited to announce that with PostSharp 2.1 we’ve enhanced the errors and warnings with the exact location information, allowing you to simply double-click on the message and you’ll be taken to the error line!

To enable this feature, go to Tools – Options – PostSharp, and under Experimental, set Resolve Message Location to True:

Then, simply rebuild your solution, and if there are any warnings or errors, you’ll be able to see exactly where they are:

This is accomplished by specifying the member (in this case, the method) that is responsible for the message, in the aspect’s CompieTimeValidate method:

// Validate the attribute usage.
public override bool CompileTimeValidate( MethodBase method )
{
    // Don't apply to constructors.
    if ( method is ConstructorInfo )
    {
        Message.Write( method, SeverityType.Error, "CX0001", 
                       "Cannot cache constructors." );
        return false;
    }

    MethodInfo methodInfo = (MethodInfo) method;

    // Don't apply to void methods.
    if ( methodInfo.ReturnType.Name == "Void" )
    {
        Message.Write( method, SeverityType.Error, "CX0002", 
                       "Cannot cache void methods." );
        return false;
    }

    // Does not support out parameters.
    ParameterInfo[] parameters = method.GetParameters();
    for ( int i = 0; i < parameters.Length; i++ )
    {
        if ( parameters[i].IsOut )
        {
            Message.Write( method, SeverityType.Error, "CX0003", 
                           "Cannot cache methods with return values." );
            return false;
        }
    }

    return true;
}

Aspect developers are encouraged to include the member in error/warning messages. For more information, please refer to the documentation on Working with Errors, Warnings and Messages.

Please note that this is not enabled by default as it is still experimental and might have an impact on performance. Please let us know how it works out for you!

Happy PostSharping!

-Igal

As most of you know, PostSharp’s transformation (weaving) of aspects into your assemblies happens after the compilation. One of the most requested features is the ability to see the actual code that is produced by PostSharp. Until now, you had to manually open the newly compiled assembly in your favorite decompiler to see the produced code.

We are delighted to announce that we’ve made viewing the source code in your favorite decompiler much easier – via a single click on the enhanced class or method:

By clicking the See enhanced source code link for the first time, you will be asked to select the decompiler you want to use (we currently support dotPeek, ILSpy and Reflector). You can always change the decompiler later from Tools – Options – PostSharp:

From now on, when you click on the See enhanced source code, your chosen decompiler will open and show you exactly the source code, as it was modified by PostSharp!

This feature is available in the latest version of PostSharp!

Happy PostSharping!

-Igal

One of the breaking innovations of PostSharp 1.0 in 2005 was the ability to execute aspect code at build time. Whereas other AOP frameworks developed complex declarative syntaxes to express “pointcuts”, PostSharp just allowed you to use System.Reflection to select the target of aspects. LINQ made it even easier to express complex code queries.

Yet, some queries were difficult to achieve just with System.Reflection. For instance, it is fairly difficult and inefficient to get all properties annotated with the [DataMember] custom attribute: you have to enumerate all types (and do a recursion on nested types), get all properties of these types, and check the presence of this custom attribute on all properties. Wow. If we were querying a relational database, we would probably create an index on the Type column of the CustomAttribute table. Well, the analogy is not so stupid. Metadata in a .NET assembly is in fact a relational database, and there is a CustomAttribute table. What is more, PostSharp already builds these indexes internally. So why not making them available to user code? This was the principal idea behind this new feature: reflection search.

Reflection Search is simply this: a set of methods making it easier and more efficient to query metadata of the assembly being processed by PostSharp. Therefore, this API is available only at build time.  It is not intended to “improve” System.Reflection for run-time use. That said, if you need to do some complex reflection query at runtime, it’s better to do it at build time using PostSharp, serialize the result and store it as a managed resource.

The API is exposed in the class PostSharp.Reflection.ReflectionSearch. Note that the feature is available in the Professional Edition only.

Enumerating Custom Attributes

Custom attributes of a type

The first set of methods you will find on the ReflectionSearch class allow you to enumerate custom attributes. GetCustomAttributesOnType retrieve all custom attributes of a given type in the current assembly (remember that this works only at build time, so the notion of “current assembly” refers to the assembly being processed by PostSharp). The second overload takes an additional parameter ReflectionSearchOptions. If you specify the value IncludeDerivedTypes, you will get all custom attributes of the specified type or any type derived from it.

There is no example in the system class library to illustrate a hierarchy of custom attributes, so let's create our own:

// A hierarchy of custom attributes.

class FruitAttribute : Attribute {}

class AppleAttribute  : FruitAttribute {}

class OrangeAttribute : FruitAttribute {}

class VegetableAttribute : Attribute {}

class TomatoAttribute : VegetableAttribute {}

// Using the custom attributes

[Fruit]
class Team
{
   [Apple]
   Dude tom;

   [Orange]  
   Dude jerry;

   [Tomato]
   Dude donald;

}

// Enumerating the custom attributes (build-time)
class MyAspect : AssemblyLevelAspect, IAspectProvider
{
 
    public IEnumerable ProvideAspects(object target)
    {

      CustomAttributeInstances[] attributes = ReflectionSearch.GetCustomAttributesOfType( 
typeof(FruitAttribute), ReflectionSearchOptions.IncludeDerivedTypes ); // TODO: Do something with that. } }

 

The method GetCustomAttributesType will return three instances of the custom attribute: (FruitAttribute, Team), (AppleAttribute ,Team.tom) and (OrangeAttribute, Team.jerry).

If you wonder why the method does not return a tomato: it is by decision of the U.S. Supreme Court, which, on May 10, 1893, declared that tomatoes are vegetables because – although they are classified as fruits in botany –  they are usually served with dinner and not dessert. As far as I am concerned, I still don’t eat tomatoes for dessert, the only thing that changed is that we are now much more accustomed to bureaucracy (and today’s tomatoes have better resistance to pressure because the species were selected to accommodate mechanical picking, and long storage and transportation – so arguably we now eat more tomatoes than in the XIXth century, but they are probably less tasty).

Anyway.

Note that the method returns a CustomAttributeInstance, which includes information about the custom attribute and the element of code to which it is applied.

Multicast attributes

Keep in mind that ReflectionSearch reflects the internal repository of custom attributes. This repository does not only include custom attributes that you add to your code manually. It also includes all “pseudo” custom attributes added by different components of PostSharp, starting with multicast attributes (remember that aspect class typically derive from MulticastAttribute).

When you use multicast custom attributes in your code, PostSharp executes the multicasting algorithm to populate the internal repository. The repository then contains the concrete instances of the custom attribute.

Let’s take an example:

[MulticastAttributeUsage( MulticastTargets.Method )]
class FooAttribute : MulticastAttribute {}

[Foo]
class MyClass
{
   void MyMethod() {}
}

In that case the repository contains an instance of FooAttribute on MyMethod but not on MyClass. The normal reflection API would give the opposite result (at least when it is run inside PostSharp or before PostSharp), because it is not aware of multicast semantics.

Since you can’t use normal reflection to retrieve multicast custom attributes, ReflectionSearch offers a second method: GetCustomAttributesOnTarget. As the name suggests, it returns the list of all custom attributes on a given element of code.

Summary

The high-level library PostSharp.dll now offers access to the internal repository of custom attributes. Since this repository, and all indexes, are used by PostSharp itself, using this new feature has minimal impact on build time. Now, you have a way to query custom attributes by type without killing performance. And you are finally able to query attributes that were created by PostSharp as the result of the multicasting algorithm.

But that’s not all ReflectionSearch has to offer. Next in line: browse relationships between elements of code. But this is for another day.

Happy PostSharping!

-gael