Learn Resharper PostFix and Source Templates

karenpayneoregon

Karen Payne

Posted on July 31, 2023

Learn Resharper PostFix and Source Templates

In this article learn how to create and use Jetbrains ReSharper’s Source templates and to explore Postfix templates.

Note
All source templates presented are in the GitHub repository


ReSharper Download a Free 30-day trial, no evaluation key required.

ReSharper system requirements


Postfix templates

With these templates a developer can write less code in many cases.

Simple example, we want to write the following code which without Postfix templates everything needs to be hand typed.

using (var cn = new SqlConnection())
{

}
Enter fullscreen mode Exit fullscreen mode

With PostFix templates type

Working with SqlClient

new SqlConnection()
Enter fullscreen mode Exit fullscreen mode

Next type using and press Enter

initial response

After pressing Enter there is a prompt to use var or the type, use Up and Down arrows to select.

select type for using statement

Press TAB and name choices appear, use Up and Down arrows to select or type in your own name.

select name for variable

Create a foreach

The task is to iterate data read from a file using a foreach which should look like the following.

List<Customers> customersList =
    JsonSerializer.Deserialize<List<Customers>>(
        File.ReadAllText("Customers.json"));

foreach (var customer in customersList!)
{
    Console.WriteLine($"{customer.Id,-3}{customer.Company}");
}
Enter fullscreen mode Exit fullscreen mode

🔹 Step 1, create the model.

public class Customers
{
    public int Id { get; set; }
    public string Company { get; set; }
    public string Title { get; set; }
    public string Contact { get; set; }
    public string Country { get; set; }
    public string Phone { get; set; }
    public DateTime Modified { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

🔹 Step 2, read the file

List<Customers> customersList =
    JsonSerializer.Deserialize<List<Customers>>(
        File.ReadAllText("Customers.json"));
Enter fullscreen mode Exit fullscreen mode

Type the variable name, . then foreach (no upper casing) and press Enter

selecting foreach

to get a prompt same as last example for var or type then variable name.

PostFix templates list

See the following documentaton for a list of postfix templates.

Also, under Resharper options they are listed and can be turned off.

Postfix options in Visual Studio

Source templates

These templates are really cool to create your own postfix templates were the template is for a specific project or solution as per documentation. Templates can be created in the same project they will be used in or create a Visual Studio solution for source templates only and reference the class project into your projects.

Working with DateTime, DateOnly and TimeOnly

The task is to get parts for a DateOnly.

Our source

static DateOnly BirthDate() 
    => new(2022, 9, 2);
Enter fullscreen mode Exit fullscreen mode

Extract Month, Day and Year

var dateOnly = BirthDate();
var month = dateOnly.Day;
var year = dateOnly.Year;
var day = dateOnly.Day;
Enter fullscreen mode Exit fullscreen mode

Or we can Deconstruct were after typing var dateOnly = BirthDate();

Deconstruct context option

Which is possible using the following method incuded in SourceTemplateLibrary class project along with other similar methods.

After accepting

var (day, month, year) = BirthDate();
Enter fullscreen mode Exit fullscreen mode

Code For BirthDate()

static DateOnly BirthDate() 
    => new(2022, 9, 2);
Enter fullscreen mode Exit fullscreen mode

To create the above with a source template.

  • Create a static class
  • Add the following NuGet package JetBrains.Annotations
  • Create the following extension method
[SourceTemplate]
public static void ds(this DateTime sender)
{
    var (day, month, year) = sender;
}
Enter fullscreen mode Exit fullscreen mode
  • Builds the project
  • Type BirthDate() for this example follows bs ds, press Enter

using ds template

And Resharper provides

var (day, month, year) = BirthDate();
Enter fullscreen mode Exit fullscreen mode

Let's say you don't need one of the parts, use a discard.

var (day, _, year) = BirthDate();
Enter fullscreen mode Exit fullscreen mode

The same can be done for a TimeOnly, create the following extension method.

public static class TimeOnlyExtensions
{
    public static void Deconstruct(this TimeOnly time, out int hour, out int minutes, out int seconds, out int milliseconds)
        => (hour, minutes, seconds, milliseconds) = 
            (time.Hour, time.Minute, time.Second, time.Microsecond);
}
Enter fullscreen mode Exit fullscreen mode

Create the source template in a static class

[SourceTemplate]
public static void ds(this TimeOnly sender)
{
    var (hour, minutes, seconds, milliseconds) = sender;
}
Enter fullscreen mode Exit fullscreen mode

Note
Two things, Reshaper uses lower casing for source templates which is done here, secondly, the names were kept simple ds for Deconstruct. Feel free to use different names that make sense to you.

Suppose there is a need to see if a DateTime is a weekday or weekend.

Create the following class for logic to see if a date is a weekday or weekend.

public static class DateTimeExtensions
{
    public static bool IsWeekend(this DateTime self) 
        => self.DayOfWeek is DayOfWeek.Sunday or DayOfWeek.Saturday;

    public static bool IsWeekDay(this DateTime self)
        => !self.IsWeekend();

    public static bool IsWeekDay(this DayOfWeek sender)
    {
        return sender is DayOfWeek.Monday or 
            DayOfWeek.Tuesday or 
            DayOfWeek.Wednesday or 
            DayOfWeek.Thursday or 
            DayOfWeek.Friday;
    }

    public static bool IsWeekend(this DayOfWeek sender) => !sender.IsWeekDay();
}
Enter fullscreen mode Exit fullscreen mode

Create the source template in a static class. Note //$ $END$ which is the final cursor position.

[SourceTemplate]
public static void weekday(this DateTime sender)
{
    if (sender.IsWeekDay())
    {
        //$ $END$
    }
}
Enter fullscreen mode Exit fullscreen mode

Now to iterate a list of DateTime the final results for this code sample will be...

var dates = DateTimesList();

foreach (var date in dates)
{
    if (date.IsWeekDay())
    {
        Console.WriteLine(date.DayOfWeek);
    }
}
Enter fullscreen mode Exit fullscreen mode

With the following source

private static List<DateTime> DateTimesList()
    => Enumerable.Range(1, 7)
        .Select(day => new DateTime(2023, 7, day))
        .ToList();
Enter fullscreen mode Exit fullscreen mode

Once the following has been entered

var dates = DateTimesList();
Enter fullscreen mode Exit fullscreen mode

Type dates dates.foreach and press Enter to use the built in postfix template. We get the following.

foreach (var dateTime in dates)
{

}
Enter fullscreen mode Exit fullscreen mode

Place the cursor in the body of the foreach and type the following to use the custom source template.

dateTime.weekday
Enter fullscreen mode Exit fullscreen mode

Press Enter or TAB and the following is written.

foreach (var dateTime in dates)
{
    if (dateTime.IsWeekDay())
    {

    }
}
Enter fullscreen mode Exit fullscreen mode

Working with a data provider DataReader

In this example the task is to iterate a SqlDataReader from a SqlCommand.

🔸 Desired finished code

var statement = "SELECT CountryId, [Name] FROM dbo.Countries;";
var connectionString = _configuration.GetValue<string>("ConnectionStrings:ApplicationConnection");
using SqlConnection cn = new(connectionString);
using SqlCommand cmd = new(statement, cn);
try
{
    cn.Open();
    SqlDataReader? reader = cmd.ExecuteReader();
    while (reader.Read())
    {

    }
}
catch (Exception exception)
{
    Console.WriteLine(exception.Message);
}
Enter fullscreen mode Exit fullscreen mode

Even if the developer types fast with source templates the above code can be in about 20 seconds or less.

This example is done in a Console project so there are several NuGet packages needed. Open the project file and note packages starting with Microsoft.Extensions.

The connection string is in appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "ApplicationConnection": "Data Source=.\\SQLEXPRESS;Initial Catalog=EF.UsingInterfaces;Integrated Security=True;Encrypt=False"
  }
}
Enter fullscreen mode Exit fullscreen mode

Add the following variable for getting the connection string

private static IConfiguration? _configuration;
Enter fullscreen mode Exit fullscreen mode

Now lets use one standard postfix template and two custom source templates.

Data to read

Data to read in SSMS

Create the following method

static void SqlClientExample()
{
    var statement = "SELECT CountryId, [Name] FROM dbo.Countries;";

}
Enter fullscreen mode Exit fullscreen mode

Under var statment type the following and press Enter

new SqlConnection().create
Enter fullscreen mode Exit fullscreen mode

Which writes out the following

static void SqlClientExample()
{
    var statement = "SELECT CountryId, [Name] FROM dbo.Countries;";

    var connectionString = _configuration.GetValue<string>("ConnectionStrings:ApplicationConnection");
    using SqlConnection cn = new(connectionString);
    using SqlCommand cmd = new("statement", cn);
    try
    {
        cn.Open();

    }
    catch (Exception exception)
    {
        Console.WriteLine(exception.Message);
    }
}
Enter fullscreen mode Exit fullscreen mode

Remove the quotes on statement

using SqlCommand cmd = new(statement, cn);
Enter fullscreen mode Exit fullscreen mode

Under cn.Open() type the following and press Enter

cmd.reader
Enter fullscreen mode Exit fullscreen mode

Which writes out a variale for a SqlDataReader and a while statement as follows.

static void SqlClientExample()
{
    var statement = "SELECT CountryId, [Name] FROM dbo.Countries;";

    var connectionString = _configuration.GetValue<string>("ConnectionStrings:ApplicationConnection");
    using SqlConnection cn = new(connectionString);
    using SqlCommand cmd = new(statement, cn);
    try
    {
        cn.Open();
        SqlDataReader? reader = cmd.ExecuteReader();
        while (reader.Read())
        {

        }

    }
    catch (Exception exception)
    {
        Console.WriteLine(exception.Message);
    }
}
Enter fullscreen mode Exit fullscreen mode

Add a line to read out data to the console and run the code.

while (reader.Read())
{
    Console.WriteLine($"{reader.GetInt32(0),-3}{reader.GetString(1)}"); 
}
Enter fullscreen mode Exit fullscreen mode

Razor Pages/ASP.NET Core

To get a connection string for EF Core in Program.cs this is one method.

builder.Services.AddDbContext<Context>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("ApplicationConnection"))
        .EnableSensitiveDataLogging());
Enter fullscreen mode Exit fullscreen mode

The following is only here to show how to create a source template for a DbContext.

Create the following class where source templates reside.

internal class Context : DbContext
{
}
Enter fullscreen mode Exit fullscreen mode

Note
In this case your DbContext is named Context, change it for the DbContext used in your project.

Now the following source templates can be used.

public static class AspNetCoreTemplates
{
    [SourceTemplate]
    public static void connectstring(this WebApplicationBuilder builder)
    {
        var connectionString = builder.Configuration.GetConnectionString("ApplicationConnection");
    }

    [SourceTemplate]
    public static void connectionpool(this WebApplicationBuilder builder)
    {
        builder.Services.AddDbContextPool<Context>(options =>
            options.UseSqlServer(
                builder.Configuration.GetConnectionString("ApplicationConnection")));
    }

    [SourceTemplate]
    public static void connection(this WebApplicationBuilder builder)
    {
        builder.Services.AddDbContext<Context>(options =>
            options.UseSqlServer(
                builder.Configuration
                    .GetConnectionString("ApplicationConnection")));
    }
}
Enter fullscreen mode Exit fullscreen mode

In Program.cs type builder.connection and press Enter to write the following.

public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        builder.Services.AddDbContext<Context>(options =>
            options.UseSqlServer(
                builder.Configuration
                    .GetConnectionString("ApplicationConnection")));
Enter fullscreen mode Exit fullscreen mode

SqlClient SqlDataReader DateOnly TimeOnly

Using NuGet package Microsoft.Data.SqlClient version 5.1.1 (at the time of this article) its possible to return DateOnly and TimeOnly using SqlClient data provider.

First create several extension methods

public static class SqlClientExtensions
{
    public static DateOnly GetDateOnly(this SqlDataReader reader, int index)
        => reader.GetFieldValue<DateOnly>(index);

    public static TimeOnly GetTimeOnly(this SqlDataReader reader, int index)
        => reader.GetFieldValue<TimeOnly>(index);
}
Enter fullscreen mode Exit fullscreen mode

In a static class add the following source template

[SourceTemplate]
[Macro(Target = "dto")]
public static void gdo(this SqlDataReader reader, int index)
{
    var dto = reader.GetDateOnly(index); 
}
Enter fullscreen mode Exit fullscreen mode

Where there is a SqlDataReader type and press Enter

reader.gdo
Enter fullscreen mode Exit fullscreen mode

The following is written, first prompting for a ordinal position in place of index

var dto = reader.GetDateOnly(index);
Enter fullscreen mode Exit fullscreen mode

Enter the index, press TAB to optionally change the current variable name from dto to something useful.

Simple generic Enum source template

Add the following method to a static class

[SourceTemplate]
[Macro(Target = "T")]
[Macro(Target = "varName")]
public static void checker<T>(this string sender, T type) where T : struct
{
    if (Enum.TryParse(sender, true, out T varName))
    {

    }
}
Enter fullscreen mode Exit fullscreen mode

When invoked

  • There is a prompt for T to enter an enum
  • Press TAB for a prompt for a out variable name

Usage

public enum DemoEnum
{
    One,
    Two,
    Three
}
Enter fullscreen mode Exit fullscreen mode

In your code add

var value = "one";
Enter fullscreen mode Exit fullscreen mode

Type value.checker and the following is written

output from checker

  • Enter the type
  • TAB
  • Enter the variable name
var value = "one";

if (Enum.TryParse(value, true, out DemoEnum result))
{

}
Enter fullscreen mode Exit fullscreen mode

Summary

With what has been presented a developer can use the source templates provided along with created their own templates along with knowledge that Postfix templates built into ReSharper can reduce coding time.

Source code

Clone the following GitHub repository and run the script under ConsoleApp1 project in the Scripts folder.

Projects

When creating a library for personal use consider separating functionality into their own projects. Example, one library for working with data, another for working with dates and time, another for file operations.

Project Description
SourceTemplatesLibrary Contains all templates
SqlClientLibrary Contains only templates for SqlClient namespace
CommonTemplateLibrary Example for how a developer would create a library of reguarly used templates

Resharper

Written with version 2023.1.4

Download a Free 30-day trial, no evaluation key required.

Microsoft Visual Studio

Using version 2022 version 17.4.5

Download Visual Studio

💖 💪 🙅 🚩
karenpayneoregon
Karen Payne

Posted on July 31, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related