Thursday, April 27, 2017

Creating an IOC Container for ASP.NET Core

I recently added support for ASP.NET Core to my Tact.NET IOC Container, and I thought that I would share some of the interesting requirements I discovered while doing so. I had originally expected the default ASP.NET Core container would follow the same rules as the official Microsoft Unity container, but that turned out not to be the case!

1) Register is first in win.

The Unity container was last in win, and it would completely disregard the original registration. With ASP.NET Core you need to preserve the original registration and then treat all subsequent registrations as addition registrations that will only be resolved when ResolveAll is invoked, similar to keyed registrations in Unity. Which brings us to our next difference...

public class RegisterIsFirstInWinTests
{
    [Fact]
    public void Unity()
    {
        var log = new EmptyLog();
        using (var container = new TactContainer(log))
        {
            container.RegisterSingleton<IExample, ExampleA>();
            container.RegisterSingleton<IExample, ExampleB>();
 
            var example = container.Resolve<IExample>();
            Assert.IsType<ExampleB>(example);
        }
    }
 
    [Fact]
    public void AspNetCore()
    {
        var log = new EmptyLog();
        using (var container = new AspNetCoreContainer(log))
        {
            container.RegisterSingleton<IExample, ExampleA>();
            container.RegisterSingleton<IExample, ExampleB>();
 
            var example = container.Resolve<IExample>();
            Assert.IsType<ExampleA>(example);
        }
    }
 
    public interface IExample
    {
        string Name { get; }
    }
 
    public class ExampleA : IExample
    {
        public string Name => nameof(ExampleA);
    }
 
    public class ExampleB : IExample
    {
        public string Name => nameof(ExampleB);
    }
}

Sunday, April 16, 2017

How to make a dotnet CLI Tool

Good news, everyone! It is remarkably easy to make a new dotnet CLI (Command Line Interface) tool! I recently created a CLI tool for one of my new projects, Tact.NET RPC, and in this post I will be referencing that project as my example.

The Basics

Step 1) Create your CLI Console App

All you have to do is...

  1. Create a normal .NET Core Console App.
    • NOTE: Currently, the dotnet CLI only supports netcoreapp1.0
  2. Rename the assembly to be prefixed with "dotnet-"
  3. dotnet pack the project and put the package in your local NuGet package source

...that is it! It is literally that easy to create your CLI tool!

Recommendation: use Microsoft.Extensions.Configuration to parse your command line arguments in a standard way.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp1.0</TargetFramework>
    <AssemblyName>dotnet-tactrpcgen</AssemblyName>
    <PackageId>Tact.Rpc.Generator</PackageId>
    <Version>1.0.3</Version>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="1.1.1" />
  </ItemGroup>
</Project>

Step 2) Consume your CLI Tool NuGet Package

Edit your csproj file and add a DotNetCliToolReference element that references your package.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard1.6</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <DotNetCliToolReference Include="Tact.Rpc.Generator" Version="1.0.3" />
  </ItemGroup>
</Project>

Now you are able to invoke your console app via the dotnet command line whenever it is executed in the same path as the csproj.

That's it; it really is that easy!

Development Tips

Here is a simple way to automate the creation and consumption of your CLI tool NuGet package during development.

Thursday, March 30, 2017

C# String Interpolation Performance

Time for a follow up to my String.Concat vs String.Format Performance post from back in 2014!

I recently found out that string interpolation is not nearly as efficient as I would have thought. I also suspected that it was just doing a string concatenation, but it is actually doing a string format. This leads to a pretty significant performance degradation; the following test runs one million iterations of each.

Number
of Args
Interpolation
Milliseconds
String.Format
Milliseconds
String.Concat
Milliseconds
String Add
Milliseconds
StringBuilder
Milliseconds
2 262 260 19 18 34
3 367 367 25 24 35
4 500 513 31 32 41
5 646 635 67 66 44
6 740 723 79 76 49
7 802 819 86 85 52
8 938 936 97 98 58

So, what's the lesson? Don't use string interpolation in high performance areas (such as your logger)!

Enjoy,
Tom

Tuesday, February 28, 2017

WebSocket Support for .NET Core

Full WebSocket support is coming with .NET Standard 2.0, which has now been delayed until Q3. In the meantime, there are still a few options to work with...

If you want to use Microsoft.AspNetCore.WebSockets.Server, I have added a middle ware wrapper that feel a lot more like Fleck:

public void Configure(IApplicationBuilder app)
{
    app.UseWebSockets();
    app.UseWebSocketHandler("test", connection =>
    {
        // Register your listeners here
        connection.OnMessage = m =>
        {
            if (m == "hi")
                connection.SendAsync("bye");
        };
    });
}

Enjoy,
Tom

Sunday, February 26, 2017

Run .NET Core xUnit tests from ReSharper in VS2015

Visual Studio 2017 is literally only a few days away from release; so it might be a little late, but I finally figured out how to run .NET Core xUnit tests from ReSharper in VS2015! Good News: If you can't upgrade to VS2017 right away, then at least you can still run your unit tests!

Just make sure that the following is included in your project.json file (with the appropriate runtime):

{
  "testRunner": "xunit",
 
  "dependencies": {
    "dotnet-test-xunit": "2.2.0-preview2-build1029",
    "xunit": "2.2.0"
  },
 
  "frameworks": {
    "netcoreapp1.0": {
      "imports": "dnxcore50"
    }
  },
 
  "runtimes": {
    "win10-x64": {}
  }
}

Enjoy,
Tom

Tuesday, January 31, 2017

.NET Standard Adoption as of January 2017

Updated 2/16 to include Elasticsearch

As should be obviously from my recently blog posts, I have really been enjoying working with .NET Core. Clearly I am not alone, as a significant number of libraries have been porting over to the .NET Standard.

Below is a list libraries that have added support for the .NET Standard, meaning that they should be able to run cross platform on both Windows and Linux.

While I have not yet had the opportunity to try all of the libraries listed below, I have had great luck with the ones that I have tested, and I am simply ecstatic to see this list growing as fast as it is.

Technology NuGet Package .NET Standard Support
Autofac Autofac Released for 1.1
Cassandra DataStax C# Driver for Apache Cassandra Released for 1.5
Couchbase Couchbase SDK 2.0 Beta for 1.5
Elasticsearch Elasticsearch.Net Released for 1.3
Kafka Confluent.Kafka Preview for 1.3
log4net Apache log4net Released for 1.3
MongoDB MongoDB.Driver Released for 1.4
NLog NLog Beta for 1.3
RabbitMQ RabbitMQ.Client Released for 1.5
RavenDB RavenDB Client Released for 1.3
Redis StackExchange.Redis Released for 1.5
Sqlite Microsoft.EntityFrameworkCore.Sqlite Released for 1.3
WebSocket Client WebSocket4Net Released for 1.3

How have these libraries been working out for you? Is there a better option than what I have listed? Please leave a comment and let me know!

Enjoy,
Tom

Sunday, January 29, 2017

.NET JsonContent for HttpClient

.NET already comes with a nice collection of HttpContent serializers, but it lacks a JsonContent type. A common solution is to just serialize their payload to a JSON string and that insert that into an instance of StringContent. However, this means that you need to remember to set your headers, and it is a little bit inefficient because of how it creates multiple strings and buffers for each payload.

I have create a simple implementation of JsonContent that uses Json.NET and pooled memory streams. The result is between 2% and 10% faster, and causes ~50% fewer garbage collections.

Check out the implementation in Tact.NET:

Enjoy,
Tom

Real Time Web Analytics