Merging Build.Directory.props

April 04, 2018 msbuild .net

MSBuild version 15 introduced the concept of "Directory.Build.props" files. From the docs:

  • Directory.Build.props is a user-defined file that provides customizations to projects under a directory. This file is automatically imported from Microsoft.Common.props unless the property ImportDirectoryBuildTargets is set to false.

What is not stated here is that only one Directory.Build.props will be imported automatically. Imagine your project exists in the directory C:\repo\src\foo\foo.csproj and there exists a file in both C:\repo\src\Directory.Build.props and C:\repo\Directory.Build.props then only C:\repo\src\Directory.Build.props will be automatically included when building C:\repo\src\foo\foo.csproj. If you would like C:\repo\Directory.Build.props to be included as well, then C:\repo\src\Directory.Build.props will have to include C:\repo\Directory.Build.props like so:

<Project>
    <Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
</Project>

This is documented here.

Snowball V2.0

February 23, 2018 .net snowball c#

I haven't written anything new here in a very long time and a lot has happened since then. I started a new job at BeumerGroup this year and now work mostly in TypeScript writing an html5 spa app.

In my spare time I've decided to working on version 2.0 of my Snowball, my 2D game framework. I've been playing around with the idea for a while now. This version will be developed directly for .net core and will be developed with cross platform capability in mind. The api will look similar but will have some changes.

The old repo is still available on my github at https://github.com/smack0007/Snowball_v1.

LINQ calls IEqualityComparer<T>.GetHashCode() before Equals()

November 24, 2014 .net linq

This is a problem that has bitten me more than a few times so I thought it was about time to write a blog post about it. It's one of those problems that makes you scratch your head for a bit and then the light bulb goes on and you remember you've solved this one before. It occurs whenever you use a LINQ extension method which takes an instance of IEqualityComaparer.

Read More

Adding assembly references in Roslyn

April 15, 2014 .net c# roslyn

In the Roslyn preview that was released at Build 2014 the way references to global assmeblies are added was changed. Before the preview I could use code like this:

var compilation = Compilation.Create(assemblyName, new CompilationOptions(OutputKind.DynamicallyLinkedLibrary))
	.AddReferences(MetadataReference.CreateAssemblyReference("mscorlib"))
	.AddReferences(MetadataReference.CreateAssemblyReference("System"))
	.AddReferences(MetadataReference.CreateAssemblyReference("System.Core"))
	.AddReferences(new MetadataFileReference(this.GetType().Assembly.Location))
	.AddSyntaxTrees(syntaxTree);

The static factory method "MetadataReference.CreateAssemblyReference" added a reference to global assemblies such as "mscorlib.dll" or "System.dll". In the Roslyn preview, the same be achieved like so:

var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);

var compilation = CSharpCompilation.Create(assemblyName)
	.WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
	.AddReferences(new MetadataFileReference(Path.Combine(assemblyPath, "mscorlib.dll")))
	.AddReferences(new MetadataFileReference(Path.Combine(assemblyPath, "System.dll")))
	.AddReferences(new MetadataFileReference(Path.Combine(assemblyPath, "System.Core.dll")))
	.AddReferences(new MetadataFileReference(Assembly.GetEntryAssembly().Location))
	.AddSyntaxTrees(syntaxTree);

Using Component Glue to build your object graphs automatically

Component Glue is an IoC container and you use it of course to wire up your object graphs for you. Component Glue can also build your object graphs for you automatically if there are no interfaces involved. Take this example:

In After.cs, you can see that Component Glue is able to build the entire object graph for us. This will include all future dependencies as well so long as interfaces don't come into play. Should an interface be needed, you can just bind that single component.

This is a very powerful thing. If one component needs to take on a dependency, just ask for it in the constructor and Component Glue will handle it for you.