Embedding additional files in an MSBuild binary log file

 
 
  • Gérald Barré
MSBuild binary logger allows us to investigate build issues in depth. It records all the events that occur during a build, and it can be replayed to reproduce the build. I've already written about this logger in previous posts: Exploring a MSBuild binary log using the binary log viewer, Detecting Double-Writes in MSBuild using the binlog. By default, the binlog file contains the content of all MSBuild… [read more]

Removing allocations by reducing closure scopes using local variables

 
 
  • Gérald Barré
Lambdas can use variables from the enclosing methods (documentation), unless the lambda is static. When a variable is captured, the compiler generates code to create the bridge between the enclosing method and the lambda. Let's consider this simple example: public void M() { var a = 0; // Create a lambda that use "a" from the enclosing method var func = () => Console.WriteLine(a); func(); } When compiling… [read more]

Reading a stream of JsonDocuments separated by new lines (ndjson)

 
 
  • Gérald Barré
There are formats where you need to read a stream of JsonDocuments separated by a character such as a new line. For instance, you can try to read data from a ndjson response. In this post, I'll show you how to read such a stream. A basic solution would be to split the stream by the separator and then parse each part. However, the JSON document may contain the separator character. For instance, if you use… [read more]

File paths in a Roslyn analyzer or source generator

 
 
  • Gérald Barré
In Roslyn, a SyntaxTree represents the content of a source file. If you need to know the source file that created this SyntaxTree, you can use the FilePath property. This property represents the file path on the disk. But, the file path on the disk may not be what you want. On CI, you should use reproducible builds to get deterministic paths (ContinuousIntegrationBuild=true and <SourceRoot>). In this… [read more]

Customizing the behavior of record copy constructors

 
 
  • Gérald Barré
When you use a record. you can create a new instance by using the new keyword. Or you can copy an instance with some modifications using with expression (non-destructive mutation). The with expression copy all fields from the original instance and then apply the modifications. var john = new Sample("John", "Doe"); var Jane = john with { FirstName = "Jane" }; record Person(string FirstName, string… [read more]

Customizing the name of embedded resources in .NET

 
 
  • Gérald Barré
When you use embedded resources in a .NET project, the resource name is computed from the path of the file. By default, it uses a format similar to <Assembly Name>.<File Path>. But the file path doesn't contain a path separator (/ or \). Instead, the path separator is replaced by a dot (.). For example, the resource name for the file resources/index.html is MyAwesomeProject.resources.index.html. So, if… [read more]