Resharper – annotation attributes

1. Introduction

I think one of the most important features of Resharper is on-the-fly code quality analysis. Basically, every time Resharper finds possible pitfall in code, it indicates this with appropriate warning. The most common warning is “Possible System.NullReferenceException”. You can easily reproduce it by writing this code

singledefaultwarning
As you can see R# is able to figure out, that LINQ SingleOrDefault function can return null. However there is no warning if we try to do something like that

So it got me thinking, how Resharper recognizes whether or whether not to show warnings. It turned out, that it uses annotation attributes, which describe behavior of functions, properties, classes and interfaces.

2. Source code annotations

In order to use these attributes we have to place them in our project. First of all, let’s create Annotation.cs file and then copy default implementation of annotations into this file. The default implementation can be found in Code annotation option (Resharper->Options->Code Inspections->Code Annotations) under the button “Copy default implementation to clipboard”.
resharperOptions
annotationoptions
From now on we can decorate our functions with e.g. CanBeNull attribute

and we will get warning if necessary
annotation attributes
Of course there are a lot more of attributes to use. My favorites are:

  • StringFormatMethodAttribute
    annotation attributes

  • PathReferenceAttribute
    annotation attributes

  • NotifyPropertyChangedInvocatorAttribute
  • annotation attributes

3. External code annotations

In case we do not have access to source code, we still are able to use annotation attributes. However we have to define annotations in xml configuration file. Let’s say we want to decorate NHibernte’s SaveOrUpdate function with NotNullAttribute. First of all we have to create xml file with appropriate declaration (This is standard XML Document Comment file. You can read specification here and here.)

Having prepared configuration file, we need to place it in appropriate location in order for Resharper to use it. It can be stored in

  • [ReSharper install directory]\Bin\ExternalAnnotations\[Assembly name].xml
  • [ReSharper install directory]\Bin\ExternalAnnotations\[Assembly name][Any name].xml.

So in my case the location is

After restarting Visual Studio, Resharper should load the file and show warning messages.
nhibernate

4. Generating initial XML annotation files

Creating xml annotation file for large library is very tedious task, fortunately Resharper have a hidden feature which can help us with generating initial xml file. First of all we have to run Visual Studio with /ReSharper.Internal parameter. In this mode we have an access to undocumented/hidden features of Resharper. Now, in the “Resharper” menu there is one additional menu item – Internal, where You can find Annotator submenu in which resides Annotate item.
annotator
Now You can specify for which dll Resharper should generate xml annotation file.
annotatorwindow
and after a while You should get complete xml declaration.
annotatorprogress
Please bear in mind, that Annotator is not official R# feature, so there is no guarantee that generating annotation files will succeed. Source code for this post can be found here

Resharper – annotation attributes

Argument validation with attributes and Ninject interceptor

1. Introduction

It is a common practice to validate function arguments before running actual code. Usually validation looks like that:

There is nothing wrong with this code, however we have to repeat this piece of code in every function. Of course we could create some helper class for argument validation and call approperiate validation function before launching rest of the code

However I was searching for more universal way for argument validation. That is why, I decided to try function interceptors and attributes.

2. Creating validation attributes

Let’s start for creating base attribute

In the next step let’s create specialized attribute for “not null” validation. This argument may look this way:

3. Using IInterceptor interface

That was an easy part, now it’s necessary to somehow intercept function execution and run attribute validation.In .NET there is no build-in mechanism to do that,that is why I’ll use extension for Ninject – Ninject Interception. First of all we have to add to our project three dll’s

  • Ninject
  • Ninject.Extensions.Interception
  • Ninject.Extensions.Interception.LinFu

You can easily add them using NuGet. Having all necessary files added to solution,let’s create function interceptor – ValidaitionInterceptor.

As You can see ValidationInterceptor implements interface IInterceptorwhich belongs to Ninject.Extensions.Interception. This interface has one method Intercept which is called before function from registered component is called. In this function I iterate over all function attributes of type ArgumentValidationAttribute and call ValidateArgument function. If validation passess function invocation.Proceed() is called, which continues execution of original function.

4. Example of usage

In order to take advantage of benefits of function interceptors, we have to resolve objects from Ninject container. First of all I’ll create some examplorary classes

In the next step I’ll create simple wrapper for Ninject container and register CarRepository in Kernel

Please, notice that registration of CarRepository was used with option Intercept().With(). Thanks to this configuration,everytime we call method from CarRepository, Intercept method from ValidaitionInterceptor will be called first. Now, it is time to use our repository,we could do that this way

Argument entity in method Update from interface IRepository was decorated with NotNull, that is why our validation mechanism should throw exception.
CallingValidationInInterceptor
Argument validation

5. Validation of return value

Using IInterceptor we could go one step further and also validate return value of method. In order to do that, we have to slightly modify Intercept method in ValidaitionInterceptor class.

We also have to change attribute usage of ArgumentValidationAttribute to

Now, we can decorate function GetAll with NotNullattribute

Since this moment, everytime function GetAll returns null, the ArgumentNullException will be thrown.

6. Drawbacks

Unfortunately using attributes for argument validation have some drawbacks. First of all, argument validation is based on function interceptors, and as I mentioned before only function, which are in objects, which are resolved from IoC container can be intercepted. What is more, interceptors allow us to intercept only functions marked as virtual or inhirited from interface. Source code for this post can be found here

Argument validation with attributes and Ninject interceptor