Announcing PostSharp 4.2 RC

by Gael Fraiteur on 22 Oct 2015

We are done! After 10 months of development, the team is happy to announce that PostSharp 4.2 is now fully finished, tested and documented, and since we reached a zero-known-bug status, we’re more than relieved to say that the RC quality level has been reached. We don’t make a difference between RC and RTM quality level, which means that we consider PostSharp 4.2 to be ready, just needing more end-customer testing.

You can download PostSharp 4.2 from our website or from NuGet (make sure to enable the pre-release option as usually). The documentation is available for download but not yet for online browsing.

What’s New in PostSharp 4.2?

In the previous blog posts (see Preview 1, Preview 3 and Preview 4 announcements), we announced the following features:

  • Full support for Visual Basic;
  • Ready-made patterns: amazing performance improvements;
  • Ready-made patterns: support for System.Collections.Immutable;
  • Ready-made patterns: support for programmatic rules;
  • Thread-safety policy;
  • INotifyPropertyChanged: support for INotifyPropertyChanging;
  • Module initializers;
  • OnAspectsInitialized advice;
  • Code metrics: hand-written code and code saved by PostSharp;
  • Customizable advice descriptions.

Today, we are announcing the following new features:

  • Support for ASP.NET v5;
  • NotifyPropertyChanged: support for Elvis operator and conditional branches;
  • NotifyPropertyChanged: method to manual raise OnPropertyChanged / OnPropertyChanging;
  • NotifyPropertyChanged: basic support for dependencies on collections;
  • Code Contracts: check output values;
  • Fixed debugging experience in async methods;
  • Actor: support non-async methods returning a value.

Experimental Support for ASP.NET v5

Even if ASP.NET v5 is still preview, we are already providing some experimental support for it. Given the high fragility of ASP.NET v5 public APIs, we are shipping the ASP.NET v5 connector in a separate open-source project named PostSharp.Dnx, hosted on GitHub. Please look at the PostSharp.Dnx project home page for instructions.

This experimental connector only supports the .NET Framework, i.e. neither CoreCLR nor Mono is supported.

Note that our plan is to merge PostSharp.Dnx into our main PostSharp package when ASP.NET v5 and the PostSharp connector will be more stable.

To make it possible to open-source the DNX connector, we had to publish a new NuGet package named PostSharp.Compiler.Client, which defines an API to invoke PostSharp. The MSBuild connector now also uses PostSharp.Compiler.Client.

Improvements to NotifyPropertyChanged

Support for Elvis operator, conditional expressions and more

Since the beginning, our NotifyPropertyChanged aspect has supported chained dependencies (when a property depends on a property of a property). With PostSharp 4.2, we will not only support the dot operator, but also the Elvis operator. Consider the example below:

[NotifyPropertyChanged]
class CustomerViewModel
{
    public CustomerModel Model { get; set; }

    public string FullName 
{
get
{ return string.Format("{0} {1} from {2}", this.Model?.FirstName, this.Model?.LastName,
this.Model?.Address?.City); }
} }

Note how the FullName property depends on the this.Model?.Address?.City chain. This is a very common scenario in MVVM applications, but it is generally very cumbersome to implement INotifyPropertyChanged in this situation. This is why PostSharp is so useful here. Unfortunately, this was not possible in PostSharp 4.1 because of the Elvis operator. We fixed that in PostSharp 4.2.

It apparently seems like a small change, but because we are analyzing MSIL and not C#, we actually had to add support for conditional branches and local variables. I will skip the full technical details, but basically we support the following kind of constructs:

[NotifyPropertyChanged]
class AddressFallback
{
    public Address Address1 { get; set; }
public Address Address2 { get; set; } public string City
{
get
{ return (this.Address1 ?? this.Address2)?.City; }
} }

In the example above, PostSharp would detect a dependency from AddressFallback.City to both Address1.City and Address2.City. If we would have expressed the same logic with ?: or an if-else, PostSharp would have detected the same dependencies as well.

Raise OnPropertyChanged and OnPropertyChanging

These methods are named SignalPropertyChanged and SignalPropertyChanging and they are exposed on the NotifyPropertyChangedServices class.

Dependencies to collections

When you add the [AggregateAllChanges] attribute to a field or automatic property, any change to a property of the object assigned to this field/property will be interpreted as a change to the field/property itself. The attribute now works only for collections.

Code Contracts: output parameters and return values

You can now add a code contract to the return value of a method or to its out/ref parameters. The code contract will be verified when the method returns (not on exception).

For instance, you can do this:

public interface IFoo
{
[return:Required]
string GetName();

void GetName([Required] out string name);
}

Actor: support for non-async methods returning a value

We are now allowing non-async non-void methods on actors. The method will be executed on the actor’s message queue but the caller will wait synchronously for the method execution to complete. Exceptions are dispatched to the caller.

This introduces an ambiguity with the behavior of non-async void methods, because the previous behavior was to execute them asynchronously, without requiring the caller to wait for the result. To resolve the ambiguity, we now require non-async void methods to be explicitly annotated with the [Dispatched] custom attribute. In the next major version, we will remove this requirement and non-async void methods will be called synchronously (but executed on the actor queue).

Summary

PostSharp 4.2 is a huge release, with major usability and performance improvements in many existing features. We’ve put the quality bar very high for this RC and we are pretty confident that the roll up will be smooth.

As with any RC, we suggest that customers test the new release in a separate branch of their source repository, run the build and the tests, and report any problem found. The whole point of publishing an RC is to gather customer feedback, and by reporting issues you are contributing to make the RTM better.

Thank you, and Happy PostSharping!

-gael