Open-source project
devlooped/ThisAssembly avatar
devlooped/ThisAssembly

ThisAssembly: turning build metadata into compile-time constants

Expose project and assembly level information as constants in the ThisAssembly class using source generators powered by Roslyn.

532 stars24 forksC#MIT

At a glance

What is it?
ThisAssembly is a family of Roslyn source generators that expose assembly attributes, MSBuild items and Git state as a static class of constants, so code can read its own version or timeout without reflection. The code is MIT licensed, but revenue-generating users are asked to pay an Open Source Maintenance Fee, and only C# is generated.
Who is it for?
Adopt ThisAssembly if you want build metadata in your code as compile-time constants rather than reflection or duplicated literals, and you are working in C#. Do not adopt it if you need F# or VB output, since the project states that for now only C# code is generated, and do not adopt it in a commercial product before reading the maintenance fee terms, because the source is MIT but revenue-generating users are asked to pay an Open Source Maintenance Fee.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 9 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 20, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One partial class, extended by a package per feature

ThisAssembly exposes project and assembly level information as constants in a class called ThisAssembly, using source generators powered by Roslyn.

The entry point is deliberately simple. The main generated type is ThisAssembly in the global namespace, by default, and it is declared as partial so you can extend it with manually created members. An MSBuild property, $(ThisAssemblyNamespace), sets a root namespace for it if the global namespace is not what you want.

The partial class is the load-bearing design decision. Each package in turn extends that same partial class to add its own nested types and members, so the feature packages compose rather than conflict. A project that takes only the assembly info package gets one set of members, and a project that takes the meta-package gets all of them, but the surface always looks like one class.

The ThisAssembly meta-package includes all the other packages for convenience, which is the easy starting point and also the way to pick up a feature package added later without changing your dependency list.

The audience is a .NET developer who is tired of the same three patterns: reading the version by reflection, duplicating a literal that also exists in the project file, or reading a timeout from configuration at runtime when the build already knew the answer. The library turns build-time knowledge into code the compiler checks.

One limitation is stated in the README without elaboration: for now, ThisAssembly only generates C# code.

Assembly attributes as constants, emitted by default

The ThisAssembly.AssemblyInfo package generates a static ThisAssembly.Info class with public constants exposing attribute values that are generated by default for SDK style projects.

The attributes covered are the ones you would otherwise read by reflection. AssemblyConfigurationAttribute, AssemblyCompanyAttribute, AssemblyTitleAttribute, AssemblyDescriptionAttribute, AssemblyProductAttribute and AssemblyCopyrightAttribute, and separately AssemblyVersionAttribute, AssemblyInformationalVersionAttribute and AssemblyFileVersionAttribute. So the configuration and the version numbers are exposed as separate sets, which is the useful distinction, since a build pipeline often stamps a configuration while the informational version comes from somewhere else entirely.

The behaviour with existing attributes is worth noting, because it decides whether you have to remove anything from your project. If your project includes these attributes by other means, they will still be emitted properly on the ThisAssembly.Info class. So the generator does not conflict with a hand-written AssemblyInfo.cs, it produces the same constants either way.

The generation is automatic for SDK style projects, which is the part that makes it useful rather than a curiosity. A classic-style project with its own Properties/AssemblyInfo.cs is a different story, and the README's wording, generated by default for SDK style projects, is the hint that the defaults are tied to the SDK style project system.

The practical payoff is that a consumer of your library can write ThisAssembly.Info.Version and get a compile-time constant, so the compiler catches the typo, and the value can never be stale at runtime because there is no runtime lookup to go out of date.

MSBuild items as typed constants, configurable from the environment

The ThisAssembly.Constants package generates a static ThisAssembly.Constants class with public constants for @(Constant) MSBuild items in the project. The items are declared in the project file like this:

xml
  <ItemGroup>
    <Constant Include="Foo.Bar" Value="Baz" Comment="Yay!" />
  </ItemGroup>

The interesting part is what these values can be. They can use values from MSBuild properties, which makes compile-time values configurable via environment variables or command line arguments:

xml
  <PropertyGroup>
    <HttpDefaultTimeoutSeconds>10</HttpDefaultTimeoutSeconds>
  </PropertyGroup>
  <ItemGroup>
    <Constant Include="Http.TimeoutSeconds" 
              Value="$(HttpDefaultTimeoutSeconds)" 
              Type="int" 
              Comment="Default timeout in seconds for HTTP requests" />
  </ItemGroup>

And the generated constant is consumed as a normal typed member:

csharp
public HttpClient CreateHttpClient(string name, int? timeout = default)
{
    HttpClient client = httpClientFactory.CreateClient(name);
    client.Timeout = TimeSpan.FromSeconds(timeout ?? ThisAssembly.Constants.Http.TimeoutSeconds);
    return client;
}

The README spells out the typing rule. If a type is provided, the generated code uses the specified type as-is, as well as the Value attribute, and it is up to the user to ensure they match and result in valid C#. A boolean, a long or a double are all possible, and if no type is provided, string is assumed. Values can also be multi-line, in which case C# raw string literals are used if the target language version supports them, that is version 11 or later.

The stated use case is test projects, where you can change the behaviour of the system under test without changing code, and the example makes that concrete by saying you could change how your product behaves by setting the environment variable HttpDefaultTimeoutSeconds in CI.

There is a shorthand for file paths. Rather than declaring a Constant for every file, you can use a FileConstant item that includes the project content:

xml
  <ItemGroup>
    <FileConstant Include="@(Content)" />
  </ItemGroup>

That is the difference between a constant per file and one declaration for all of them, and it is the form you would use in a test project that needs to know where its fixtures live.

Git state without a build-time script

The ThisAssembly.Git package generates a static ThisAssembly.Git class with constants for Git properties of the current project. The set is small and each entry has a rule attached.

Commit is the full commit hash. Sha is the first 9 characters of that commit. Root is the repository root path, normalized to forward slashes, which is the detail that matters for anyone constructing a path at runtime on Windows. Url is the repository URL, and only when PublishRepositoryUrl is set to true. Branch comes from CI environment variables.

That last one is the item to think about. Branch is not read from Git, it is read from the environment, which means the value depends on your CI system naming its variables the way the generator expects. Locally, without those variables, the branch constant will not be what a developer expects from a local checkout.

The package depends on the project's installed Microsoft.SourceLink.* package reference, which the README states as a requirement rather than a recommendation. SourceLink is what maps the commit to the source it came from, and the generated Url constant only exists when the repository URL is published, so the two settings are connected.

The general pattern across the packages is the same one the whole library is built on: information that only the build knows, turned into a constant the compiler can see. The version, the configuration, the file paths, the timeout, the commit. None of it is read at runtime, all of it is checked at compile time, and the cost is a dependency on a source generator running in your build.

MIT code, a maintenance fee, and one language

The licence picture needs two sentences and both of them are in the README.

The source code is freely available under the terms of the license.txt, and the repository badges show an MIT licence with a license.txt file. But the project also carries an Open Source Maintenance Fee section, and the wording is specific. Users of this package who generate revenue must pay an Open Source Maintenance Fee, and while the source code is freely available under the terms of the License, the package and other aspects of the project require adherence to the Maintenance Fee, with a separate osmfeula.txt in the repository and a EULA badge pointing at it. To pay the fee you become a Sponsor at the appropriate OSMF tier, and a single fee covers all of the Devlooped packages.

That is a commercial arrangement layered over an MIT code base, and it is different from the usual open source bargain in a way a corporate legal team should look at rather than assume. The MIT grant of the code remains, and the fee is a condition the project attaches to use of the package. Whether that arrangement is enforceable or acceptable in your organisation is a question for your counsel, not for this article. What matters for an engineer evaluating the dependency is that it is not a zero-cost package in the sense most MIT packages are, and that the fee is tiered by revenue rather than by company size.

The other boundary is the language. The README says that for now ThisAssembly only generates C# code. That is a hard limit for an F# or VB.NET shop, and it is worth noting that the project itself is written in C#.

The release record is healthy. The listed versions are v2.1.6 from 2026-09-28, v2.1.5 and v2.1.4 both from 2026-08-27, and the last push was on 2026-10-15. The repository is not archived, and it carries a changelog.md, a ThisAssembly.slnx, a src/ directory and an assets/ directory.

Editorial conclusion

Adopt ThisAssembly if you want build metadata in your code as compile-time constants rather than reflection or duplicated literals, and you are working in C#. Do not adopt it if you need F# or VB output, since the project states that for now only C# code is generated, and do not adopt it in a commercial product before reading the maintenance fee terms, because the source is MIT but revenue-generating users are asked to pay an Open Source Maintenance Fee. Verify first that the assembly attributes you want are emitted by default in your project style, that the version of the meta-package you take pulls in the feature packages you actually need, and that the constant types you declare in MSBuild produce valid C#.

Frequently asked questions

What does ThisAssembly generate?

It exposes project and assembly level information as constants in a partial ThisAssembly class using Roslyn source generators. The main generated type is ThisAssembly in the global namespace by default, and each feature package extends that same partial class with its own nested types and members.

Which assembly attributes does ThisAssembly.AssemblyInfo expose?

It generates a static ThisAssembly.Info class with public constants for the configuration, company, title, description, product and copyright attributes, and for the version, informational version and file version attributes. These are generated by default for SDK style projects, and if the attributes are also present by other means they are still emitted properly on the class.

Can ThisAssembly constants be configured from the environment?

Yes. The Constant item takes its value from an MSBuild property, so the value can come from environment variables or command line arguments. The README gives the example of an Http.TimeoutSeconds constant typed as int, which can be changed in CI by setting the HttpDefaultTimeoutSeconds environment variable without changing code.

Does ThisAssembly work with F# or VB.NET?

No, not currently. The README states that for now ThisAssembly only generates C# code, and the project itself is written in C#. The MSBuild property $(ThisAssemblyNamespace) can be used to set a root namespace for the generated class.

What licence applies to ThisAssembly?

The source code is available under the terms of the MIT license in license.txt, but the README also states that users of this package who generate revenue must pay an Open Source Maintenance Fee, with the terms in osmfeula.txt. A single fee at the appropriate tier covers all Devlooped packages.

Official sources

  1. devlooped/ThisAssembly on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/devlooped-thisassembly.svg)](https://hysenlabs.com/projects/devlooped-thisassembly)

Was this useful?