Creating Nuget Packages from .Net SDK style projects (.net core, etc)

When you use project files with the new .Net SDK project specification, you can easily expose those projects as nuget packages, via msbuild or the dotnet pack command. This is useful, as you don’t need to use nuget.exe, and you do not need to author and maintain a nuspec file.

Nuget.exe does not fully understand the new SDK project format, and also does not understand multi-targetting, so you might not have Nuget.exe as an option.

GeneratePackageOnBuild

To get your project to build a nuget package, you can set the GeneratePackageOnBuild element in your project file to true.

  <PropertyGroup>
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
  </PropertyGroup>

This is nice and simple, but it can slow down your build process, as it generates a package on each build, even when you don’t need a package generating.

IsPackable

You can specify whether a project is packable. This defaults to true, so if you don’t specify IsPackable, and run dotnet pack, every project will get packed, even the ones you don’t want to pack!

  <PropertyGroup>
    <IsPackable>true</IsPackable>
  </PropertyGroup>

By using IsPackable, you can split build and pack into two individual steps, and have more finely grained control over your package creation.

Including other assets in your packages

You can include assets from your project by adding them as an item in your project file.

  <ItemGroup>
    <None Include="AppIcon.ico" Pack="true" PackagePath="\" />
  </ItemGroup>

You can even get fancy and include whole folders by using wildcards. A single wildcard will take everything in the path you’ve specified, whereas a double wildcard will recursively include everything including child folders.

  <ItemGroup>
    <None Include="images\**" Pack="true" PackagePath="\" />
  </ItemGroup>

For more information on using wildcards, refer to the msdn documentation.

Making a self contained package

If you want to expose an application as a nuget package, you may need to directly include all dependencies in your nuget package. This is required if you wish to make the package available over chocolatey.

⚠️To achieve this, we need to work around a few quirks. Project items can only refer to items that exist before the build is executed, but what if we want to pack items that were produced as part of a build?

The answer is to build and pack as two separate steps. By doing this, all of the build artefacts have been created, and can be referenced before we execute the pack step.

Including build artefacts in a package

If you’re authoring a package that only targets a single version of the .Net Framework, you can achieve this using the following code:

  <ItemGroup>
    <None Include="bin\$(Configuration)\$(TargetFramework)\**" Visible="false">
      <PackagePath>lib\$(TargetFramework)</PackagePath>
      <Pack>true</Pack>
      <InProject>false</InProject>
      <Visible>false</Visible>
    </None>
  </ItemGroup>

Here we include everything from the current build configuration and target framework folders in the package, under the appropriate lib framework directory.

If your project targets multiple framework versions, the $(targetFramework) variable will not be defined. The code needs to be slightly modified.

  <ItemGroup>
    <None Include="bin\$(Configuration)\**" Visible="false">
      <PackagePath>lib</PackagePath>
      <Pack>true</Pack>
      <InProject>false</InProject>
      <Visible>false</Visible>
    </None>
  </ItemGroup>

Here we include everything from the current build configuration folder, and rely on the fact that each framework build will output to the correctly named framework folder. We then package these under lib.

Don’t forget to remove your dependencies

Now we’ve included all of our dependencies directly in our package, we need to tell the packer that we don’t need any external dependencies. You can do this by setting the PrivateAssets attribute on your package references to “All”.

<ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Configuration" Version="1.1.2" PrivateAssets="All" />
    <PackageReference Include="SimpleInjector" Version="4.9.0" PrivateAssets="All" />
</ItemGroup>

You also need to do this with your project references.

  <ItemGroup>
    <ProjectReference Include="..\Project1\Project1.csproj" PrivateAssets="All" />
    <ProjectReference Include="..\Project2\Project2.csproj" PrivateAssets="All" />
  </ItemGroup>

.Net thread safety and best practices – the double checked lock pattern

Thread safety is a very important topic for any developer, and can be challenging to understand for anyone new to working with multi-threading.  Race conditions are, by nature, very challenging to debug, so it is very important to have a good mental model of how a program will execute.

Continue reading

Chocolate chip shortbread

Chocolate chip shortbread recipe

This recipe makes some really nice crumbly shortbread.  I developed this recipe from a basic shortbread “3-2-1” recipe, so-called because it’s 3 parts flour, 2 parts butter and 1 part sugar.  I tweaked this recipe gradually to my personal preference.  I’ve since developed quite a few variants, but this recipe is the classic one that all of my colleagues and family enjoy.  I hope you do too.
Continue reading