Writing Implicit and Explicit C# Conversion Operators

When writing custom classes we can provide behaviour to allow for both explicit and implicit conversions to other types.

Implicit conversion operators are those that don’t require an explicit cast.

Explicit conversion operators are those that do require an explicit cast.

As an example, the following code shows a simple console application to covert a weight in Pounds to Kilograms.

internal class Program
{
    private static void Main(string[] args)
    {
        WriteLine("Please enter a value in lbs");
        var lbsText = ReadLine();

        var lbs = new PoundsExplicit(float.Parse(lbsText));
        WriteLine($"\nYou entered {lbs}");

        Kilogram kg = (Kilogram) lbs;
        WriteLine($"\n{lbs} is {kg}");

        WriteLine("\nPress enter to exit");
        ReadLine();
    }
}

Notice in the preceding code the line Kilogram kg = (Kilogram) lbs; is explicitly casting from a type of PoundsExplicit to Kilograms.

The Kilogram class is defined as follows:

internal class Kilogram
{
    public float Weight { get; set; }

    public Kilogram(float weight)
    {
        Weight = weight;
    }

    public override string ToString()
    {
        return $"{Weight} kg";
    }
}

To allow the (explicit) cast from PoundsExplicit to Kilogram, the PoundsExplicit class defines an explicit conversion operator as shown in the following code:

internal class PoundsExplicit
{
    public float Weight { get; set; }

    public PoundsExplicit(float weight)
    {
        Weight = weight;
    }
    public override string ToString()
    {
        return $"{Weight} lbs";
    }

    public static explicit operator Kilogram(PoundsExplicit lbs)
    {
        const float conversionRate = 0.45359237f;

        float equivalentKgs = lbs.Weight * conversionRate;

        return new Kilogram(equivalentKgs);
    }
}

To allow the conversion to Kilogram to be implicit, with no cast required (e.g. Kilogram kg = lbs;) the operator can be changed to implicit as shown in the following class:

internal class PoundsImplicit
{
    public float Weight { get; set; }

    public PoundsImplicit(float weight)
    {
        Weight = weight;
    }       

    public override string ToString()
    {
        return $"{Weight} lbs";
    }

    public static implicit operator Kilogram(PoundsImplicit lbs)
    {
        const float conversionRate = 0.45359237f;

        float equivalentKgs = lbs.Weight * conversionRate;

        return new Kilogram(equivalentKgs);
    }
}

The main method can now be modified as follows:

private static void Main(string[] args)
{
    WriteLine("Please enter a value in lbs");
    var lbsText = ReadLine();

    var lbs = new PoundsImplicit(float.Parse(lbsText));
    WriteLine($"\nYou entered {lbs}");

    Kilogram kg = lbs;
    WriteLine($"\n{lbs} is {kg}");

    WriteLine("\nPress enter to exit");
    ReadLine();
}

Notice in the preceding code the conversion from PoundsImplicit to Kilogram now is implicit, it does not require an explicit cast.

When deciding between implicit or explicit conversion operators you should consider the resulting readability of code that uses the types. An implicit cast is more convenient whereas an explicit cast may add extra clarity/readability to the code that uses the types.

SHARE:

Using the C# 6.0 nameof Operator in ASP.NET MVC Razor Views

Traditionally to reference an action and/or a controller in a Razor view the action/controller name is represented as a string as shown in the following code:

<ul class="nav navbar-nav">
    <li>@Html.ActionLink("Home", "Index", "Home")</li>
    <li>@Html.ActionLink("About", "About", "Home")</li>
    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>

This means that some brittleness can be introduced into the application, for example if the name of the controller or action is changed these strings can become outdated and cause a runtime error.

The nameof operator introduced in C# 6.0 gets the (non fully qualified) name of the type passed to it. So for example nameof(HomeController) will return the string “HomeController”. The nameof operator can also be used with type members, for example nameof(HomeController.Index) will return the string “Index”.

The following code shows the use of nameof to get the action name programmatically without needing a magic string:

<ul class="nav navbar-nav">
    <li>@Html.ActionLink("Home", nameof(HomeController.Index), "Home")</li>
    <li>@Html.ActionLink("About", nameof(HomeController.About), "Home")</li>
    <li>@Html.ActionLink("Contact", nameof(HomeController.Contact), "Home")</li>
</ul>

Now if the name of the HomeController.Index method is renamed, for example to HomeController.Index2, there will be a build time error: “'HomeController' does not contain a definition for 'Index'”.

The use of nameof can also be applied to the controller name:

<ul class="nav navbar-nav">
    <li>@Html.ActionLink("Home", nameof(HomeController.Index), nameof(HomeController) )</li>
    <li>@Html.ActionLink("About", nameof(HomeController.About), nameof(HomeController))</li>
    <li>@Html.ActionLink("Contact", nameof(HomeController.Contact), nameof(HomeController))</li>
</ul>

The preceding code however causes errors, the link URL produced is “http://localhost:26663/HomeController/About” rather than the correct “http://localhost:26663/Home/About” (note the extra Controller text).

One way to rectify this would be to remove the word “Controller” from the string produced by nameof:

<ul class="nav navbar-nav">
    <li>@Html.ActionLink("Home", nameof(HomeController.Index), nameof(HomeController).Replace("Controller", ""))</li>
    <li>@Html.ActionLink("About", nameof(HomeController.About), nameof(HomeController).Replace("Controller", ""))</li>
    <li>@Html.ActionLink("Contact", nameof(HomeController.Contact), nameof(HomeController).Replace("Controller", ""))</li>
</ul>

This technique introduces some code duplication, which could be addressed by creating a string extension method:

public static class ControllerExtensions
{
    public static string RemoveController(this string fullControllerClassName)
    {
        return fullControllerClassName.Replace("Controller", "");
    }
}

And then using this extension method:

<ul class="nav navbar-nav">
    <li>@Html.ActionLink("Home", nameof(HomeController.Index), nameof(HomeController).RemoveController())</li>
    <li>@Html.ActionLink("About", nameof(HomeController.About), nameof(HomeController).RemoveController())</li>
    <li>@Html.ActionLink("Contact", nameof(HomeController.Contact), nameof(HomeController).RemoveController()))</li>
</ul>

Alternatively a static method could be created:

public static class ControllerExtensions
{
    public static string ShortControllerName<T>() where T : Controller
    {
        return typeof(T).Name.Replace("Controller", "");
    }
}

And then called from the view:

<ul class="nav navbar-nav">
    <li>@Html.ActionLink("Home", nameof(HomeController.Index), ControllerExtensions.ShortControllerName<HomeController>())</li>
    <li>@Html.ActionLink("About", nameof(HomeController.About), ControllerExtensions.ShortControllerName<HomeController>())</li>
    <li>@Html.ActionLink("Contact", nameof(HomeController.Contact), ControllerExtensions.ShortControllerName<HomeController>())</li>
</ul>

This technique may not work in all situations, for example if an action method is using the [ActionName] attribute:

[ActionName("Contact2")]
public ActionResult Contact()
{    
    // ...
}
In the preceding example, nameof(HomeController.Contact) will return the string “Contact” and the URL “http://localhost:26663/Home/Contact” wheras the correct URL should be “http://localhost:26663/Home/Contact2” because of the [ActionName("Contact2")] attribute.

Note that to get access to nameof, the view needs to be compiled with C# 6.0 language features enabled.

SHARE:

New Pluralsight Course: Automated Business Readable Web Tests with Selenium and SpecFlow

SpecFlow is a tool that can translate natural language scenarios (e.g. writing in English or other spoken languages) into test code. This can allow business people, users, or other stakeholders to verify that the correct features are being built.

Selenium is a tool that allows test code (multiple programming languages supported) to automated a web browser. This allows the creation of automated UI tests that operate the web application as if an end user where doing it; for example clicking buttons and typing text into input boxes.

My new Pluralsight course shows how to integrate these two tools.

The course is organized into four modules:

  1. Introduction to Business Readable Web Testing
  2. Getting Started with Selenium
  3. Adding Business Readability with SpecFlow
  4. Creating More Maintainable Web Automation

If you’re new to SpecFlow I suggest watching this course first before moving on to Automated Business Readable Web Tests with Selenium and SpecFlow.

SHARE:

Your First Xbox One UWP App

image

There’s been a number of almost-goosebump-inspiring moments during my .NET dev experience such as the first time I saw my code running on a Windows Phone 7. Another one of these moments was seeing my code running on my Xbox One for the first time.

(Note: this post describes pre-release technology)

It is now possible to take your regular Fallout 4 playing retail Xbox One and turn it into a development machine. This allows the running of Universal Windows Platform (UWP) apps. At the time of writing this is in preview/pre-release status with a final release expected later this year.

There’s a great set of documentation on MSDN that describes the following steps in detail. I’d recommend reading through them all before starting the process as there’s a number of warnings that should be observed before starting. For example “some popular games and apps will not work as expected, and you may experience occasional crashes and data loss. If you leave the developer preview, your console will factory reset and you will have to reinstall all of your games, apps, and content” [MSDN].

Also be aware that, to enable Xbox UWP app development in Visual Studio, the Windows 10 SDK preview build 14295 needs to be installed: “Installing this preview SDK on your PC will prevent you from submitting apps to the store built on this PC, so don’t do this on your production development PC” [MSDN]. I created a new Hyper-V virtual machine so as not to disturb my base machine.

The documentation recommends using a hardwired network connection rather than wireless for better dev performance, I used wireless and for this simple app and it was fine. Also note “…system performance in this preview does not reflect system performance of the final release” [MSDN].

Also note that you don’t need the latest Windows 10 preview build to install the tools, the virtual machine I created was just running standard Windows 10 Pro, though as the following screenshot shows this seems to mean that there is no XAML visual preview in Visual Studio.

No XAML Preview without Windows 10 insider build


Overview of Steps

The following is an overview of the main steps required, once again you should consult MSDN for full details/steps required/warnings.

Step 1: Development Environment Setup

[MSDN]

You need:

  • Visual Studio 2015 Update 2 or newer (be sure to install the Universal Windows App Development Tools component)
  • Windows 10 SDK preview build 14295
  • Sign up for Windows Insider program
  • Create Windows Dev Center account
  • Network connection to your Xbox One

Step 2: Xbox One Setup

Detailed steps from MSDN.

Sign in to Xbox One.

Install Dev Mode Activation app from Xbox One store

Installing Dev Mode Activation app from Xbox One store

Once installed run the app:

Running Dev Mode Activation app

This can be a bit confusing as to what to do next, basically just leave it alone, at some point (perhaps hours) an “Update your Xbox” prompt will be displayed. Install the update and wait for it to complete and your Xbox restarted.

Open the Dev Mode Activation app again and following the instructions, to switch your console to into dev mode:

Switching Xbox One to developer mode

Tip: Make sure you’re connected to your wireless network before continuing…

Once restart is complete, open the Dev Home app:

Opening the Dev Home app

Take a note of the Xbox One’s IP address:

Xbox One IP Address

Step 3: Connection to Your Xbox One from Visual Studio

Create a new UWP project in Visual Studio.

Open the project properties and choose Remote Machine, enter the Xbox One’s IP address, and choose Universal (Unencrypted protocol).

Configuring Visual Studio to connect to Xbox One

Next run the app, and Visual Studio will ask you for a PIN, head back to the Xbox One dev app, and choose “Pair with Visual Studio”, you’ll be given a PIN that you can type into Visual Studio.

Pairing Visual Studio with Xbox One

Your app should now be installed and run on your Xbox One!

App XAML in Visual Studio

UWP app running on Xbox One

SHARE:

Free eBook C# 6.0: What’s New Quick Start Complete

free C# bok cover image

My new free eBook “C# 6.0: What’s New Quick Start” is now complete and available for download.

The book covers the following:

  • Using Static Type Directive
  • String Interpolation
  • The Null-Conditional Operators
  • Getter Only Auto Properties
  • Using Await in Catch and Finally Blocks
  • Property, Dictionary, and Index Initializers
  • The nameof Operator
  • Expression Bodied Functions and Properties
  • Exception Filters
  • Visual Studio 2015 and C# 6

You can download it for free or pay what you think it is worth.

Happy reading!

SHARE:

New Pluralsight Course: Business Readable Automated Tests with SpecFlow 2.0

My newest Pluralsight course was just published. Business Readable Automated Tests with SpecFlow 2.0 teaches how to create tests that the business can read, understand, and contribute to. These “English-like” tests (other spoken languages are supported) can be executed by writing test code that is associated with the “English-like” steps. Because the tests sit alongside the source code, they can become living (executable) documentation for the system, as opposed to an out-of-date Word document somewhere on the network for example. Check out the course here.

SHARE:

New Free eBook C# 6.0: What’s New Quick Start

C# 6 eBook Cover Image

The first chapters of my new free eBook have just been published.

The book will cover the new features added in C# 6.0 and provide a quick start to those new to version 6 or as a handy reference to those already using C# 6.0

New chapters are being added periodically and you can get the version now and get access to new chapters as they are published.

You can download the book for free or pay what you think it’s worth.

SHARE:

New Pluralsight Course: Getting Started Building Windows Services with Topshelf

My newest Pluralsight course “Getting Started Building Windows Services with Topshelf” has just been released.

Topshelf is an open source library that makes it easier to develop, test, and install Windows Services.

If you’re new to Windows Services, the course starts by introducing how Windows Services work and some of their features such as automatic service recovery and the ability to run in the background as different users.

The course then goes on to cover how to create a Windows Service with Topshelf as well as additional techniques such as debugging, logging, pause and continue and the ability to send custom commands to running services.

Check out the course link or browse all my Pluralsight courses.

SHARE:

Testing That Your Public APIs Have Not Changed Unexpectedly with PublicApiGenerator and Approval Tests

We can write automated tests to cover various aspects of the code we write. We can write unit/integration tests that test that the code is producing the expected outcomes. We can use ConventionTests to ensure internal code quality, for example that classes following a specified naming convention and exists in the correct namespace. We may even add the ability to create a business readable tests using tools such as SpecFlow or BDDfy.

Another aspect that we might want to ensure doesn’t change unexpectedly is the public API that our code exposes to callers.

Using PublicApiGenerator to Generate a Report of our Public API

The first step of ensuring our public API hasn’t changed is to be able to capture the public API in a readable way. The PublicApiGenerator NuGet package (from Jake Ginnivan) gives us this ability.

Suppose we have the following class defined:

public class Calculator
{
    public Calculator()
    {
        CurrentValue = 0;
    }

    public int CurrentValue { get; private set; }

    public void Clear()
    {
        CurrentValue = 0;
    }

    public void Add(int number)
    {
        CurrentValue += number;
    }
}

Notice here that this code defines the public API that consumers of the Calculator class can use. It’s this public API that we want to test to ensure it doesn’t change unexpectedly.

We might start with some unit tests as shown in the following code:

public class CalculatorTests
{
    [Fact]
    public void ShouldHaveInitialValue()
    {
        var sut = new Calculator();

        Assert.Equal(0, sut.CurrentValue);
    }

    [Fact]
    public void ShouldAdd()
    {
        var sut = new Calculator();

        sut.Add(1);

        Assert.Equal(1, sut.CurrentValue);
    }
}

These tests help us ensure the code is doing the right thing but do not offer any protection against the public API changing. We can now add a new test that uses PublicApiGenerator to generate a string “report” detailing the public members of our API. The following test code shows this in use:

[Fact]
public void ShouldHaveCorrectPublicApi()
{
    var sut = new Calculator();

    // Get the assembly that we want to generate the public API report for
    Assembly calculatorAssembly = sut.GetType().Assembly;

    // Use PublicApiGenerator to generate the API report
    string apiString = PublicApiGenerator.PublicApiGenerator.GetPublicApi(calculatorAssembly);

    // TODO: assert API has not changed
}

If we debug this test and look at the content of the apiString variable we’d see the following text:

[assembly: System.Runtime.InteropServices.ComVisibleAttribute(false)]
[assembly: System.Runtime.InteropServices.GuidAttribute("c2dc3732-a4a5-4baa-b4df-90f40aad1c6a")]
[assembly: System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.5.1", FrameworkDisplayName=".NET Framework 4.5.1")]

namespace Demo
{
    
    public class Calculator
    {
        public Calculator() { }
        public int CurrentValue { get; }
        public void Add(int number) { }
        public void Clear() { }
    }
}

Using Approval Tests to Assert the API Is Correct

Now in our test we have a string that represents the public API. We can combine PublicApiGenerator with the Approval Tests library to check that this API text doesn’t change.

First off we go and install the Approval Tests NuGet Package. We can then modify the test as shown below:

public class CalculatorApiTests
{
    [Fact]
    public void ShouldHaveCorrectPublicApi()
    {
        var sut = new Calculator();

        // Get the assembly that we want to generate the public API report for
        Assembly calculatorAssembly = sut.GetType().Assembly;

        // Use PublicApiGenerator to generate the API report
        string apiString = PublicApiGenerator.PublicApiGenerator.GetPublicApi(calculatorAssembly);

        // Use Approval Tests to verify the API hasn't changed
        Approvals.Verify(apiString);
    }
}

The first time we run this it will fail with a message such as “Failed Approval: Approval File "c:\…\Demo.Tests\CalculatorApiTests.ShouldHaveCorrectPublicApi.approved.txt" Not Found”. It will also generate a file called CalculatorApiTests.ShouldHaveCorrectPublicApi.received.txt. We can rename this to CalculatorApiTests.ShouldHaveCorrectPublicApi.approved.txt, run the test again and it will pass.

If we now modify the public API by changing a method signature (e.g. to public void Clear(int someParam)) and run the test again it will fail with a message such as “Received file c:\...\Demo.Tests\CalculatorApiTests.ShouldHaveCorrectPublicApi.received.txt does not match approved file c:\...\Demo.Tests\CalculatorApiTests.ShouldHaveCorrectPublicApi.approved.txt”.

Modifying the test and adding an Approval Tests reporter attribute ([UseReporter(typeof(DiffReporter))]) and running the test will now gives us a visual diff identifying the changes to the public API as shown in the following screenshot.

Approval Tests Diff Screenshot

To learn more about the features of Approval Tests, check out my Approval Tests for .NET Pluralsight course.

SHARE:

Painless .NET Windows Service Creation with Topshelf

Windows Services allow us to run code in the background, without needing (for example) a console application running continually. Windows Services can run as various system users or specific local/domain users.

To see what Windows Services are installed on your (Win 8+) PC, hit Win+x then hit G. In the Computer Management window that opens, click the Services option under Services and Applications as shown in the following screenshot.

Computer Management window showing installed Windows Services

As the preceding screenshot shows, a Service has a (Display) Name, a Description, a Status (e.g. Running or not), a Startup Type (Manual, Automatic, Disabled, etc), and a Log On As that specifies in which user context the Service executes.

We can create Windows Services to run arbitrary .NET code such as:

  • Self-hosted web server using Owin
  • File system watcher and batch processing (e.g. image file conversion, video encoding)
  • Host remote Akka.NET actor system (such as in my Pluralsight course)
  • Process messages from a message queue as they arrive (e.g. MSMQ)
  • Mail, FTP, etc. servers
  • Integration/gateway, e.g. receive data from external systems

Using Topshelf

Topshelf is an open source project that greatly simplifies the creation of Windows Services.

The overview of creating a Service using Topshelf is:

  1. Create a Console application project in Visual Studio
  2. Add the Topshelf NuGet package
  3. Create a class to represent your service logic
  4. Configure your Service using the Topshelf API
  5. Build your Console application
  6. Execute your Console application passing Topshelf parameters to install/uninstall your Service


So assuming we have a new Console project called “Time” and the following NuGet packages are installed:

<packages>
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.Owin" version="5.2.3" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.OwinSelfHost" version="5.2.3" targetFramework="net451" />
  <package id="Microsoft.Owin" version="2.0.2" targetFramework="net451" />
  <package id="Microsoft.Owin.Host.HttpListener" version="2.0.2" targetFramework="net451" />
  <package id="Microsoft.Owin.Hosting" version="2.0.2" targetFramework="net451" />
  <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net451" />
  <package id="Owin" version="1.0" targetFramework="net451" />
  <package id="Topshelf" version="3.2.0" targetFramework="net451" />
</packages>

We can create a self-hosted OWIN service that tells us the time.

First off we create an API Controller to return the time and then create an OWIN startup configuration class:

public class TimeController : ApiController
{
    [HttpGet]
    public string Now()
    {
        return DateTime.Now.ToLongTimeString();
    }
}

public class Startup
{
    public void Configuration(IAppBuilder appBuilder)
    {
        var config = new HttpConfiguration();

        config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{time}");
        config.Formatters.Remove(config.Formatters.XmlFormatter);
        config.Formatters.Add(config.Formatters.JsonFormatter);

        appBuilder.UseWebApi(config);
    }
}

Next we create a class that represents our Topshelf Windows Service:

class TimeService
{
    private IDisposable _webServer;

    public void Start()
    {
        // code that runs when the Windows Service starts up
        _webServer = WebApp.Start<Startup>("http://localhost:8084");
    }

    public void Stop()
    {
        // code that runs when the Windows Service stops
        _webServer.Dispose();
    }
}

Now in the Console applications main method we can use Topshelf’s HostFactory to configure what our Windows Service will do (via the TimeService class) and how it will be configured in Windows:

class Program
{
    static void Main(string[] args)
    {
        HostFactory.Run(
            configuration =>
            {
                configuration.Service<TimeService>(
                    service =>
                    {
                        service.ConstructUsing(x => new TimeService());
                        service.WhenStarted(x => x.Start());
                        service.WhenStopped(x => x.Stop());
                    });

                configuration.RunAsLocalSystem();

                configuration.SetServiceName("ASimpleService");
                configuration.SetDisplayName("A Simple Service");
                configuration.SetDescription("Don't Code Tired Demo");
            });
    }
}

Once the solution is built, navigate to the bin/debug directory in a admin command prompt and type:

time.exe install

This will install the Service into Windows as the following screenshots show.

command prompt showing Topshelf service installation


Service installed in Windows


In the command prompt window type:

time.exe start

This will start our new service.

Now in a browser, navigate to http://localhost:8084/api/time/now and you’ll see the current time come back as JSON

screenshot showing browser getting time

To learn more about Topshelf, check out my Pluralsight course: Getting Started Building Windows Services with Topshelf.

SHARE: