Everyone who has ever tried to create multilingual application knows, that this is very tedious task. The most repetitive work is usually moving hard-coded strings to resource files. Fortunately with Resharper this is definitelly less painfull than usuall.
In order to point out localizable parts of application , it is necessary to decorate classes with System.ComponentModel.LocalizableAttribute. However, usually we want to localize an entire program, so more universal solution is to set appropriate project configuration in properties window. To bring up this window, select project file and then press F4 button.
From now on, Resharper shows warnings indicating that our hard-coded strings might be moved to resource file. Pressing ALT+ENTER on these strings will bring up the context menu action, where new option – “Move to resource” is available.
Choosing this option will bring up the “Move to Resource” window. However if we do not have any resource files in our project, we will get this message.
In order to create these files, right click on project and choose Add->New Item. Now, select Resource.resx file and name it for example LocalizableStrings.resx.
In this resource file we will store values for our “default language”. Supporting more languages require us to create additional LocalizableString files with appropriate LETF tags suffixes.
Now, we are able to move our hard-coded string to resource files.
By default Resharper adds hard-coded strings to default resource file, so we have to specify values for localizable string for other languages. In order to do that, first navigate to resource entry in LocalizableStrings.resx file by holding CTRL and clicking property “Program_Main_This_is_localizable_string”
and then press ALT+ENTER and choose “Override ‘PropertyName…'”. This operation brings up “Edit Resource” window where You can easily navigate between resource files and update given resource property
Resharper not only is able to move strings to resource files but also can use existing ones. This basically means that if we use hard-coded string which already has been added to resource file, Resharper will suggest to use predefined resource
NHhibernate – multiple queries in one roundtrip to server
Usually when we need to retrieve data from database server, we write code which looks like that
1 2 3 4 5 6 7 8 9 10 11 |
using (var session = DataAccesLayer.Instance.OpenSession()) { using (var transaction = session.BeginTransaction()) { var projects = session.QueryOver<Project>().Where(val => val.Name == "Project").List(); var tasks = session.QueryOver<Task>().Where(val => val.Name == "First task").List(); //more queries //more queries //exception handling etc. } } |
This code will execute two queries,each of them in separate roundtrip to the server.
This is the most popular way of getting data for multiple tables etc. However it is possible to enhance the code above and execute several queries in only one roundtrip to the database server. NHibernate provides us with three different mechanisms to accomplish this goal:
- MultiQuery
- MultiCriteria
- Future
First way to execute several queries at once is MultiQuery. In my opinion this is not very handy mechanism because of the fact, that we must use HQL. Here is an example of usage
1 2 3 4 5 6 7 8 9 |
var projectQuery = session.CreateQuery("FROM Project as prj where prj.Name= :projectName") .SetParameter("projectName", "Project"); var taskQuery = session.CreateQuery( "FROM Task as tsk where tsk.Name=:taskName" ) .SetParameter("taskName","First task"); var multiQueryByIndex = session.CreateMultiQuery( ) .Add<Project>( projectQuery ) .Add<Task>( taskQuery ); |
As You can see thanks to CreateMultiQuery method we are able to aggregate multiple queries. In order to get access to results, we have to execute code below
1 |
var result = multiQueryByIndex.List(); |
Now we can get result of specific query using indexer
1 2 |
var projects = result[0] as List<Project>; var tasks = result[1] as List<Task>; |
If we don’t like this approach, the CreateMultiQuery method has an overload which allows to give “names” to queries. Thanks to this we can get result of query by its name.
1 2 3 4 5 6 |
var multiQueryByKey = session.CreateMultiQuery( ) .Add<Project>( "project", projectQuery ) .Add<Task>( "task", taskQuery ); var projects = multiQueryByKey.GetResult( "project" ) as List<Project>; var tasks = multiQueryByKey.GetResult( "task" ) as List<Task>; |
Much better way of creating multiple queries is MultiCriteria. In this case we can use QueryOver API, so we don’t have to rely on HQL query strings.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
var projectQuery = session.QueryOver<Project>().Where(val => val.Name == "Project"); var taskQuery = session.QueryOver<Task>( ).Where(val => val.Name == "First task"); var multiCriteriaByIndex = session.CreateMultiCriteria( ) .Add( projectQuery ) .Add( taskQuery ); var multiCriteriaByKey = session.CreateMultiCriteria( ) .Add( "project", projectQuery ) .Add( "task", taskQuery ); IList result = multiCriteriaByIndex.List( ); var projects = result[0] as List<Project>; var tasks = result[1] as List<Task>; projects = multiCriteriaByKey.GetResult( "project" ) as List<Project>; tasks = multiCriteriaByKey.GetResult( "task" ) as List<Task>; |
As You can see the usage of CreateMultiCriteria method is pretty consistent with CreateMultiQuery. Unfortunately we still have to retrieve data from specific query by index or by query name.
My personal favorite for creating multi queries is Future. The usage is pretty straightforward
1 2 |
var projects = session.QueryOver<Project>().Where(val => val.Name == "Project").Future<Project>(); var tasks = session.QueryOver<Task>().Where(val => val.Name == "First task").Future<Task>(); |
As You can see, we can leverage QueryOver API and instead of calling List
Despite the fact that all three mechanism has completely different syntax ,SQL created by all of them is the same and looks like that
Resharper – “Go to Everything”
In Resharper 8 JetBrains introduced new command called “Go to Everything”. You can use it by hitting the CTRL + N keys (CTRL + T with Visual Studio keyboard shortcuts layout) This command is basically combination of three features known from previous versions of Resharper, namely: “Go to Class”, “Go to Type” and “Go to Symbol”. Most common usage of this functionality is just to search classes, properties or functions.
However not everyone knows, that we can narrow down search criteria and find methods or properties in given class
What is even more interesting, is the fact that it is possible to go to specific line in searched type
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
1 2 3 |
List<object> objlList = new List<object>( ); var result = objlList.SingleOrDefault( ); Console.WriteLine( result.GetHashCode( ) ); |
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
1 2 3 4 5 6 7 8 9 10 |
private static void DisplayHashCode() { var result = Foo(); Console.WriteLine( result.GetHashCode( ) ); } private static object Foo() { return null; } |
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”.
From now on we can decorate our functions with e.g. CanBeNull attribute
1 2 3 4 5 6 7 8 9 10 11 |
private static void DisplayHashCode() { var result = Foo(); Console.WriteLine( result.GetHashCode( ) ); } [CanBeNull] private static object Foo() { return null; } |
and we will get warning if necessary
Of course there are a lot more of attributes to use. My favorites are:
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.)
1 2 3 4 5 6 7 |
<assembly name="NHibernate"> <member name="M:NHibernate.ISession.SaveOrUpdate(System.Object)"> <parameter name="obj"> <attribute ctor="M:JetBrains.Annotations.NotNullAttribute.#ctor" /> </parameter> </member> </assembly> |
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
1 |
C:\Program Files (x86)\JetBrains\ReSharper\v8.1\Bin\ExternalAnnotations\NHibernateNHibernate.xml |
After restarting Visual Studio, Resharper should load the file and show warning messages.
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.
Now You can specify for which dll Resharper should generate xml annotation file.
and after a while You should get complete xml declaration.
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
Implementing INotifyPropertyChanged without lambda expressions and “magic” strings
I think almost every .NET developer is familiar with INotifyPropertyChanged interface. Typical implementation of this interface looks more or less like that:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class NotifyPropertyBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged( Expression<Func<object>> propertyExpression ) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler( this, new PropertyChangedEventArgs( GetPropertyName( propertyExpression ) ) ); } private string GetPropertyName( Expression<Func<object>> propertyExpression ) { var unaryExpression = propertyExpression.Body as UnaryExpression; var memberExpression = unaryExpression == null ? (MemberExpression)propertyExpression.Body : (MemberExpression)unaryExpression.Operand; var propertyName = memberExpression.Member.Name; return propertyName; } } |
Thanks to lambda expressions we can get rid of so called “magic” strings when rising PorpertyChange event.
1 2 3 4 5 6 7 8 9 10 11 |
private int _myProperty; public int MyProperty { get { return _myProperty; } set { if (_myProperty == value) return; _myProperty = value; OnPropertyChanged( ( ) => MyProperty ); } } |
However, with .NET 4.5 we can even get rid of lambda expressions itself. Everything thanks to CallerMemberNameAttribute, which provides us information about caller of given method. Now we can rewrite NotifyPropertyBase class as follows
1 2 3 4 5 6 7 8 9 |
public class NotifyPropertyBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = null ) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler( this, new PropertyChangedEventArgs( propertyName)); } } |
From this moment we can call OnPropertyChanged method without any arguments
1 2 3 4 5 6 7 8 9 10 11 |
private int _myProperty; public int MyProperty { get { return _myProperty; } set { if (_myProperty == value) return; _myProperty = value; OnPropertyChanged(); } } |
and thanks to CallerMemberName attribute, argument propertyName will be filled with appropriate value.
Source code for this post can be found here