Important
Slnx is now deprecated.
The reason is that MSBuild now officially has support for reading/writing/building SLNX files. Additionally, MSBuild relies on a NuGet package: Microsoft.VisualStudio.SolutionPersistence, which is a library directly from Visual Studio that parses SLNX files with support to parse every aspect of an SLNX file, even though SLNX is an undocumented file type.
SLNX is a fast parser and writer for the (currently) new in-preview Visual Studio XML Solution format with a .slnx extension, introduced in Visual Studio 2022 17.10 Preview 3.
Slnx has been around since April 23, 2024 - days after SLNX file format was introduced.
Available on NuGet: https://nuget.org/packages/Slnx
using Slnx;
var model = SlnxModel.Load(File.ReadAllText("TestSlnx.txt"));
foreach (Folder folder in model.TopLevelFolders!)
{
foreach (string file in folder.DescendantFiles!)
{
Console.WriteLine(file);
}
}
TestSlnx.txt content:
<Solution>
<Folder Name="Solution Items">
<File Path="File1.cs" />
<File Path=".editorconfig" />
<Project Path="File.csproj" />
<Folder Name="Test">
<File Path=".editorconfig" />
<File Path="data.cs" />
</Folder>
</Folder>
</Solution>
Output:
File1.cs
.editorconfig
using Slnx;
using System.Text.Json;
// Note: This is a .NET 8 project and uses Collection Expressions.
var factory = new SlnxFactory();
var folder = new Folder("Solution Items");
folder.AddProjectWithPathOnly("./CSharp/CSharp.csproj");
folder.AddProjectWithPathOnly("./VB.NET/VB.NET.vbproj");
folder.AddProject(new Project("./DockerCompose/DockerCompose.dcproj", type: Guid.NewGuid().ToString(), config: new(solution: "*|*", project: "*|*|Deploy")));
var moreFolders = new Folder("C++");
moreFolders.AddFiles(["util.cpp", "util.h", "data.cc", "data.h"]);
folder.AddFiles(["File1.cs", "File2.cs"]);
folder.AddFolder(moreFolders);
factory.AddFolder(folder);
factory.AddProjectWithPathOnly("Slnx/Slnx.csproj");
factory.AddProjectWithPathOnly("App/App.shproj");
string content = factory.AsModel().Store();
File.AppendAllText("OutputSlnx.txt", content);
// To provide detailed information, I'll just JSONify it with System.Text.Json.
var model = SlnxModel.Load(File.ReadAllText("OutputSlnx.txt"));
Console.WriteLine(JsonSerializer.Serialize(model));
The program will generate a file named OutputSlnx.txt
with these contents:
<Solution>
<Project Path="Slnx/Slnx.csproj" />
<Project Path="App/App.shproj" />
<Folder Name="Solution Items">
<File Path="File1.cs" />
<File Path="File2.cs" />
<Project Path="./CSharp/CSharp.csproj" />
<Project Path="./VB.NET/VB.NET.vbproj" />
<Project Path="./DockerCompose/DockerCompose.dcproj" Type="a9ca3494-2d8e-43aa-a418-28709ddb90fc">
<Configuration Solution="*|*" Project="*|*|Deploy" />
</Project>
<Folder Name="C++">
<File Path="util.cpp" />
<File Path="util.h" />
<File Path="data.cc" />
<File Path="data.h" />
</Folder>
</Folder>
</Solution>
Bug reports, feature suggestions, questions, and other feedback are welcome.
Slnx uses the .NET 6.0 Runtime, but it works fine for preceding versions, including .NET 7.0, 8.0, and future releases.
Input:
<Solution>
<Folder Name="Solution Items">
<File Path="File1.cs" />
<File Path=".editorconfig" />
<Project Path="File.csproj" />
<Folder Name="Test">
<File Path=".editorconfig" />
<File Path="data.cs" />
</Folder>
</Folder>
</Solution>
Benchmark result:
BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.2861/23H2/2023Update/SunValley3)
AMD Ryzen 7 4700U with Radeon Graphics, 1 CPU, 8 logical and 8 physical cores
.NET SDK 8.0.303
[Host] : .NET 8.0.7 (8.0.724.31311), X64 RyuJIT AVX2
DefaultJob : .NET 8.0.7 (8.0.724.31311), X64 RyuJIT AVX2
Method | Mean | Error | StdDev | Gen0 | Allocated |
---|---|---|---|---|---|
ReadBenchie | 4.486 μs | 0.0301 μs | 0.0267 μs | 7.1106 | 14.55 KB |
Code:
var factory = new SlnxFactory();
var folder = new Folder("Solution Items");
folder.AddProjectWithPathOnly("./CSharp/CSharp.csproj");
folder.AddProjectWithPathOnly("./VB.NET/VB.NET.vbproj");
folder.AddProject(new Project("./DockerCompose/DockerCompose.dcproj", type: null, config: new(solution: "*|*", project: "*|*|Deploy")));
var moreFolders = new Folder("C++");
moreFolders.AddFiles(["util.cpp", "util.h", "data.cc", "data.h"]);
folder.AddFiles(["File1.cs", "File2.cs"]);
folder.AddFolder(moreFolders);
factory.AddFolder(folder);
factory.AddProjectWithPathOnly("Slnx/Slnx.csproj");
factory.AddProjectWithPathOnly("App/App.shproj");
_ = factory.AsModel().Store();
To provide the accurate benchmark, we're not saving or logging the result anywhere like console or file - we're just focusing on how fast Slnx can export the SlnxFactory instance as a string.
Benchmark result:
BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.2861/23H2/2023Update/SunValley3)
AMD Ryzen 7 4700U with Radeon Graphics, 1 CPU, 8 logical and 8 physical cores
.NET SDK 8.0.303
[Host] : .NET 8.0.7 (8.0.724.31311), X64 RyuJIT AVX2
DefaultJob : .NET 8.0.7 (8.0.724.31311), X64 RyuJIT AVX2
Method | Mean | Error | StdDev | Gen0 | Allocated |
---|---|---|---|---|---|
WriteBenchie | 4.841 μs | 0.0371 μs | 0.0310 μs | 9.4299 | 19.33 KB |