{"id":18602991,"url":"https://github.com/devlooped/thisassembly","last_synced_at":"2025-05-15T20:03:57.842Z","repository":{"id":37962154,"uuid":"295828621","full_name":"devlooped/ThisAssembly","owner":"devlooped","description":"Exposes project and assembly level information as constants in the ThisAssembly class using source generators powered by Roslyn.","archived":false,"fork":false,"pushed_at":"2025-05-15T00:10:10.000Z","size":1689,"stargazers_count":472,"open_issues_count":7,"forks_count":25,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-05-15T01:24:16.248Z","etag":null,"topics":["csharp-sourcegenerator","roslyn"],"latest_commit_sha":null,"homepage":"https://clarius.org/ThisAssembly","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/devlooped.png","metadata":{"files":{"readme":"readme.md","changelog":"changelog.md","contributing":null,"funding":null,"license":"license.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"devlooped"}},"created_at":"2020-09-15T19:25:30.000Z","updated_at":"2025-05-12T05:07:49.000Z","dependencies_parsed_at":"2024-01-06T09:55:16.694Z","dependency_job_id":"754f17de-8043-4da9-98d6-cd158b11d913","html_url":"https://github.com/devlooped/ThisAssembly","commit_stats":null,"previous_names":["kzu/thisassembly"],"tags_count":71,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devlooped%2FThisAssembly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devlooped%2FThisAssembly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devlooped%2FThisAssembly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/devlooped%2FThisAssembly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/devlooped","download_url":"https://codeload.github.com/devlooped/ThisAssembly/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254414497,"owners_count":22067272,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp-sourcegenerator","roslyn"],"created_at":"2024-11-07T02:13:10.688Z","updated_at":"2025-05-15T20:03:57.118Z","avatar_url":"https://github.com/devlooped.png","language":"C#","funding_links":["https://github.com/sponsors/devlooped","https://github.com/sponsors"],"categories":[],"sub_categories":[],"readme":"![Icon](img/icon-32.png) ThisAssembly\n============\n\n[![Version](https://img.shields.io/nuget/vpre/ThisAssembly.svg?color=royalblue)](https://www.nuget.org/packages/ThisAssembly)\n[![Downloads](https://img.shields.io/nuget/dt/ThisAssembly.svg?color=green)](https://www.nuget.org/packages/ThisAssembly)\n[![License](https://img.shields.io/github/license/devlooped/ThisAssembly.svg?color=blue)](https://github.com//devlooped/ThisAssembly/blob/main/license.txt)\n[![Build](https://github.com/devlooped/ThisAssembly/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/devlooped/ThisAssembly/actions)\n\n\u003c!-- include https://github.com/devlooped/.github/raw/main/sponsorlinkr.md --\u003e\n*This project uses [SponsorLink](https://github.com/devlooped#sponsorlink) to attribute sponsor status (direct, indirect or implicit).*\n*For IDE usage (without warnings), sponsor status is required. IDE-only warnings will be issued after a grace period otherwise.*\n\n\u003c!-- https://github.com/devlooped/.github/raw/main/sponsorlinkr.md --\u003e\n\n\u003c!-- #meta --\u003e\nExpose project and assembly level information as constants in the ThisAssembly \nclass using source generators powered by Roslyn.\n\nThe main generated entry point type is `ThisAssembly` in the global namespace (by default), \nand is declared as partial so you can extend it too with manually created members.\n\n\u003e Use `$(ThisAssemblyNamespace)` MSBuild property to set a root namespace for `ThisAssembly`.\n\nEach package in turn extends this partial class to add their own nestes types \nand members.\n\nThe [ThisAssembly](https://nuget.org/packages/ThisAssembly) meta-package includes \nall the other packages for convenience.\n\n\u003e For now, ThisAssembly only generates C# code.\n\u003c!-- #meta --\u003e\n\n## ThisAssembly.AssemblyInfo\n[![Version](https://img.shields.io/nuget/vpre/ThisAssembly.AssemblyInfo.svg?color=royalblue)](https://www.nuget.org/packages/ThisAssembly.AssemblyInfo)\n[![Downloads](https://img.shields.io/nuget/dt/ThisAssembly.AssemblyInfo.svg?color=green)](https://www.nuget.org/packages/ThisAssembly.AssemblyInfo)\n\n\u003c!-- include src/ThisAssembly.AssemblyInfo/readme.md#assembly --\u003e\n\u003c!-- #assembly --\u003e\nThis package generates a static `ThisAssembly.Info` class with public \nconstants exposing the following attribute values generated by default for SDK style projects:\n\n* AssemblyConfigurationAttribute\n* AssemblyCompanyAttribute\n* AssemblyTitleAttribute\n* AssemblyDescriptionAttribute\n* AssemblyProductAttribute\n* AssemblyCopyrightAttribute\n\n* AssemblyVersionAttribute\n* AssemblyInformationalVersionAttribute\n* AssemblyFileVersionAttribute\n\nIf your project includes these attributes by other means, they will still be emitted properly \non the `ThisAssembly.Info` class.\n\n![](https://raw.githubusercontent.com/devlooped/ThisAssembly/main/img/ThisAssembly.AssemblyInfo.png)\n\n\u003c!-- #assembly --\u003e\n\u003c!-- src/ThisAssembly.AssemblyInfo/readme.md#assembly --\u003e\n\n## ThisAssembly.Constants\n\n[![Version](https://img.shields.io/nuget/vpre/ThisAssembly.Constants.svg?color=royalblue)](https://www.nuget.org/packages/ThisAssembly.Constants)\n[![Downloads](https://img.shields.io/nuget/dt/ThisAssembly.Constants.svg?color=green)](https://www.nuget.org/packages/ThisAssembly.Constants)\n\n\u003c!-- include src/ThisAssembly.Constants/readme.md#constants --\u003e\n\u003c!-- #constants --\u003e\nThis package generates a static `ThisAssembly.Constants` class with public\nconstants for `@(Constant)` MSBuild items in the project.\n\n```xml\n  \u003cItemGroup\u003e\n    \u003cConstant Include=\"Foo.Bar\" Value=\"Baz\" Comment=\"Yay!\" /\u003e\n    \u003cConstant Include=\"Foo.Hello\" Value=\"World\" Comment=\"Comments make everything better 😍\" /\u003e\n  \u003c/ItemGroup\u003e\n```\n\n![](https://raw.githubusercontent.com/devlooped/ThisAssembly/main/img/ThisAssembly.Constants.png)\n\nThese constants can use values from MSBuild properties, making compile-time values configurable \nvia environment variables or command line arguments. For example:\n\n```xml\n  \u003cPropertyGroup\u003e\n    \u003cHttpDefaultTimeoutSeconds\u003e10\u003c/HttpDefaultTimeoutSeconds\u003e\n  \u003c/PropertyGroup\u003e\n  \u003cItemGroup\u003e\n    \u003cConstant Include=\"Http.TimeoutSeconds\" \n              Value=\"$(HttpDefaultTimeoutSeconds)\" \n              Type=\"int\" \n              Comment=\"Default timeout in seconds for HTTP requests\" /\u003e\n  \u003c/ItemGroup\u003e\n```\n\nThe C# code could consume this constant as follows:\n\n```csharp\npublic HttpClient CreateHttpClient(string name, int? timeout = default)\n{\n    HttpClient client = httpClientFactory.CreateClient(name);\n    client.Timeout = TimeSpan.FromSeconds(timeout ?? ThisAssembly.Constants.Http.TimeoutSeconds);\n    return client;\n}\n```\n\nNote how the constant is typed to `int` as specified in the `Type` attribute in MSBuild. \nThe generated code uses the specified `Type` as-is, as well as the `Value` attribute in that \ncase, so it's up to the user to ensure they match and result in valid C# code. For example, \nyou can emit a boolean, long, double, etc.. If no type is provided, `string` is assumed. Values \ncan also be multi-line and will use [C# raw string literals](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/raw-string) \nif supported by the target language version (11+).\n\nIn this example, you could trivially change how your product behaves by setting the environment \nvariable `HttpDefaultTimeoutSeconds` in CI. This is particularly useful for test projects, \nwhere you can easily change the behavior of the system under test without changing the code.\n\n\nIn addition to arbitrary constants via `\u003cConstant ...\u003e`, it's quite useful (in particular in test projects) \nto generate constants for files in the project, so there's also a shorthand for those:\n\n```xml\n  \u003cItemGroup\u003e\n    \u003cFileConstant Include=\"@(Content)\" /\u003e\n  \u003c/ItemGroup\u003e\n```\n\nWhich results in:\n\n![](https://raw.githubusercontent.com/devlooped/ThisAssembly/main/img/ThisAssembly.Constants2.png)\n\n\u003c!-- #constants --\u003e\n\u003c!-- src/ThisAssembly.Constants/readme.md#constants --\u003e\n\n## ThisAssembly.Git\n\n[![Version](https://img.shields.io/nuget/vpre/ThisAssembly.Git.svg?color=royalblue)](https://www.nuget.org/packages/ThisAssembly.Git)\n[![Downloads](https://img.shields.io/nuget/dt/ThisAssembly.Git.svg?color=green)](https://www.nuget.org/packages/ThisAssembly.Git)\n\n\u003c!-- include src/ThisAssembly.Git/readme.md#git --\u003e\n\u003c!-- #git --\u003e\nThis package generates a static `ThisAssembly.Git` class with constants \nfor the following Git properties from the current project:\n\n* Commit\n* Sha (first 9 chars from Commit)\n* Root (normalized to forward slashes)\n* Url (if PublishRepositoryUrl=true)\n* Branch (from CI environment variables)\n\n![](https://raw.githubusercontent.com/devlooped/ThisAssembly/main/img/ThisAssembly.Git.png)\n\nThis package relies on your project's installed\n[Microsoft.SourceLink.*](https://www.nuget.org/packages?q=Microsoft.SourceLink) \npackage reference according to your specific Git-based source control server \n(such as GitHub, Azure DevOps, BitBucket, etc).\n\n\u003e NOTE: from .NET 8 SDK onwards, SourceLink is included by default, so you \n\u003e don't need to add it manually.\n\nThe `Branch` property is populated from environment variables provided \nby the currently supported CI systems: GitHub Actions, Azure DevOps, \nAppVeyor, TeamCity, Travis CI, Circle CI, GitLab CI, Buddy, and Jenkins.\n\nWhenever the CI system provides a pull request number, the branch name is \n`pr[NUMBER]`, such as `pr123`. This makes it easy to use it as a semver \nmetadata label.\n\n\u003e Note: by default, the values of these constants are populated during \n\"real\" builds (that is, not IDE/design-time builds used to populate \nintellisense). This is to avoid negatively affecting the editor's \nperformance. This means, however, that the properties will seem to \nalways be empty when inspecting them in the IDE (although never at \nrun-time). If you want to force population of these values for \ndesign-time builds, set the `EnableSourceControlManagerQueries` property to `true`. \nThis property is defined and documented by \n[dotnet/sourcelink](https://github.com/dotnet/sourcelink/blob/main/src/SourceLink.Common/build/Microsoft.SourceLink.Common.props#L14).\n\nAt the MSBuild level, targets can take a dependency on the provided \n`InitializeGitInformation` target, which sets the equivalent properties\nnamed:\n\n* RepositoryCommit\n* RepositorySha\n* RepositoryRoot\n* RepositoryUrl\n* RepositoryBranch\n\nThe names of these properties were chosen on purpose to match the \nproperties used by [nuget pack](https://learn.microsoft.com/en-us/nuget/reference/msbuild-targets#pack-target) \nand [nugetizer](https://github.com/devlooped/nugetizer) to populate\nthe relevant package metadata. \n\nSo if you have a GitHub repository, installing these three packages \nwill ensure you have the proper metadata out of the box and the simplest \npackaging experience possible:\n\n```xml\n\u003cProject Sdk=\"Microsoft.NET.Sdk\"\u003e\n  \u003cPropertyGroup\u003e\n    \u003cTargetFramework\u003enetstandard2.0\u003c/TargetFramework\u003e\n  \u003c/PropertyGroup\u003e\n\n  \u003cItemGroup\u003e\n    \u003cPackageReference Include=\"Microsoft.SourceLink.GitHub\" /\u003e\n    \u003cPackageReference Include=\"ThisAssembly.Git\" /\u003e\n    \u003cPackageReference Include=\"NuGetizer\" /\u003e\n  \u003c/ItemGroup\u003e\n\u003c/Project\u003e\n```\n\n\u003c!-- #git --\u003e\n\u003c!-- src/ThisAssembly.Git/readme.md#git --\u003e\n\n## ThisAssembly.Metadata\n\n[![Version](https://img.shields.io/nuget/vpre/ThisAssembly.Metadata.svg?color=royalblue)](https://www.nuget.org/packages/ThisAssembly.Metadata)\n[![Downloads](https://img.shields.io/nuget/dt/ThisAssembly.Metadata.svg?color=green)](https://www.nuget.org/packages/ThisAssembly.Metadata)\n\n\u003c!-- include src/ThisAssembly.Metadata/readme.md#metadata --\u003e\n\u003c!-- #metadata --\u003e\nThis package provides a static `ThisAssembly.Metadata` class with public \nconstants exposing each `[System.Reflection.AssemblyMetadata(..)]` defined in \nthe project file as [supported by the .NET SDK](https://learn.microsoft.com/en-us/dotnet/standard/assembly/set-attributes-project-file#set-arbitrary-attributes).\n\nThe metadata attribute is declared using MSBuild syntax in the project \n(for .NET 5.0+ projects that have built-in support for `@(AssemblyMetadata)` items):\n\n```xml\n  \u003cItemGroup\u003e\n    \u003cAssemblyMetadata Include=\"Foo\" Value=\"Bar\" /\u003e\n  \u003c/ItemGroup\u003e\n```\n\nAnd a corresponding `ThisAssembly.Metadata.Foo` constant with the value `Bar` is provided \nfor this example.\n\n![](https://raw.githubusercontent.com/devlooped/ThisAssembly/main/img/ThisAssembly.Metadata.png)\n\n\u003c!-- #metadata --\u003e\n\u003c!-- src/ThisAssembly.Metadata/readme.md#metadata --\u003e\n\n## ThisAssembly.Project\n\n[![Version](https://img.shields.io/nuget/vpre/ThisAssembly.Project.svg?color=royalblue)](https://www.nuget.org/packages/ThisAssembly.Project)\n[![Downloads](https://img.shields.io/nuget/dt/ThisAssembly.Project.svg?color=green)](https://www.nuget.org/packages/ThisAssembly.Project)\n\n\u003c!-- include src/ThisAssembly.Project/readme.md#project --\u003e\n\u003c!-- #project --\u003e\nThis package generates a static `ThisAssembly.Project` class with public \nconstants exposing project properties that have been opted into this mechanism by adding \nthem as `ProjectProperty` MSBuild items in the project file, such as:\n\n```xml\n  \u003cPropertyGroup\u003e\n    \u003c!-- Some arbitrary MSBuild property declared somewhere --\u003e\n    \u003cFoo\u003eBar\u003c/Foo\u003e\n  \u003c/PropertyGroup\u003e\n  \u003cItemGroup\u003e\n    \u003c!-- Opt-in to emitting that property value as a constant in ThisAssembly.Project --\u003e\n    \u003cProjectProperty Include=\"Foo\" Comment=\"This comment replaces the default comment :)\" /\u003e\n  \u003c/ItemGroup\u003e\n```\n\n![](https://raw.githubusercontent.com/devlooped/ThisAssembly/main/img/ThisAssembly.Project.png)\n\n\u003c!-- #project --\u003e\n\u003c!-- src/ThisAssembly.Project/readme.md#project --\u003e\n\n## ThisAssembly.Resources\n\n[![Version](https://img.shields.io/nuget/vpre/ThisAssembly.Resources.svg?color=royalblue)](https://www.nuget.org/packages/ThisAssembly.Resources)\n[![Downloads](https://img.shields.io/nuget/dt/ThisAssembly.Resources.svg?color=green)](https://www.nuget.org/packages/ThisAssembly.Resources)\n\nThis package generates a static `ThisAssembly.Resources` class with public \nproperties exposing shortcuts to retrieve the contents of embedded resources.\n\n\u003c!-- include src/ThisAssembly.Resources/readme.md#resources --\u003e\n\u003c!-- #resources --\u003e\n\nThis package generates a static `ThisAssembly.Resources` class with public \nproperties exposing typed APIs to retrieve the contents of embedded resources.\n\n\n```xml\n  \u003cItemGroup\u003e\n    \u003cEmbeddedResource Include=\"Content/Docs/License.md\" /\u003e\n  \u003c/ItemGroup\u003e\n```\n\n![](https://raw.githubusercontent.com/devlooped/ThisAssembly/main/img/ThisAssembly.Resources.png)\n\nSince markdown files are text files, the API will expose a `Text` property property \nfor it that will read its content once and cache it:\n\n![](https://raw.githubusercontent.com/devlooped/ThisAssembly/main/img/ThisAssembly.Resources2.png)\n\nThe `$(EmbeddedResourceStringExtensions)` MSBuild property allows customizing which \nfile extensions get treated as text files. By default, it's defined as:\n\n```xml\n  \u003cPropertyGroup\u003e\n    \u003cEmbeddedResourceStringExtensions\u003e.txt|.cs|.sql|.json|.md\u003c/EmbeddedResourceStringExtensions\u003e\n  \u003c/PropertyGroup\u003e\n```\n\nYou can append additional file extensions to this list, or override it completely.\nThe list must be pipe-separated.\n\nYou can always use the provided `GetStream` and `GetBytes` for more advanced scenarios (or for \nnon-text resources).\n\nOptionally, you can specify the `Kind` metadata for a specific `EmbeddedResource` you want \ntreated as a text file:\n\n```xml\n\u003cItemGroup\u003e\n    \u003cEmbeddedResource Include=\"query.kql\" Kind=\"Text\" /\u003e\n\u003c/ItemGroup\u003e\n```\n\nYou can also add a `Comment` item metadata attribute, which will be used as the `\u003csummary\u003e` XML \ndoc for the generated member.\n\n## Adding dynamic resources\n\nYou can also provide additional embedded resources dynamically, by running a target before \n`PrepareEmbeddedResources`:\n\n```xml\n  \u003cTarget Name=\"AddDynamicResources\" BeforeTargets=\"PrepareEmbeddedResources\"\u003e\n    \u003cItemGroup\u003e\n      \u003cEmbeddedResource Include=\"Content/Docs/$(Configuration).md\" /\u003e\n    \u003c/ItemGroup\u003e\n  \u003c/Target\u003e\n```\n\n## Customizing the generated code\n\nThe following MSBuild properties can be used to customize the generated code:\n\n| Property                | Description                                                                                          |\n|-------------------------|------------------------------------------------------------------------------------------------------|\n| ThisAssemblyNamespace   | Sets the namespace of the generated `ThisAssembly` root class. If not set, it will be in the global namespace. |\n| ThisAssemblyVisibility  | Sets the visibility modifier of the generated `ThisAssembly` root class. If not set, it will be internal. |\n\n\u003c!-- #resources --\u003e\n\u003c!-- src/ThisAssembly.Resources/readme.md#resources --\u003e\n\n## ThisAssembly.Strings\n\n[![Version](https://img.shields.io/nuget/vpre/ThisAssembly.Strings.svg?color=royalblue)](https://www.nuget.org/packages/ThisAssembly.Strings)\n[![Downloads](https://img.shields.io/nuget/dt/ThisAssembly.Strings.svg?color=green)](https://www.nuget.org/packages/ThisAssembly.Strings)\n\n\u003c!-- include src/ThisAssembly.Strings/readme.md#strings --\u003e\n\u003c!-- #strings --\u003e\n\nThis package generates a static `ThisAssembly.Strings` class with public \nconstants exposing string resources in .resx files or methods with the right number of \nparameters for strings that use formatting parameters. \n\n![](https://raw.githubusercontent.com/devlooped/ThisAssembly/main/img/ThisAssembly.Strings.gif)\n\nIn addition, it groups constants and methods in nested classes according to an optional \nunderscore separator to organize strings. For example, *User_InvalidCredentials* can be\naccessed with *ThisAssembly.Strings.User.InvalidCredentials* if it contains a simple string, \nor as a method with the right number of parametres if its value has a format string.\n\nGiven the following Resx file:\n\n| Name                          | Value                                 | Comment           |\n|-------------------------------|---------------------------------------|-------------------|\n| Infrastructure_MissingService | Service {0} is required.              | For logging only! |\n| Shopping_NoShipping           | We cannot ship {0} to {1}.            |                   |\n| Shopping_OutOfStock           | Product is out of stock at this time. |                   |\n| Shopping_AvailableOn          | Product available on {date:yyyy-MM}.  |                   |\n\nThe following code would be generated:\n\n```csharp\npartial class ThisAssembly\n{\n    public static partial class Strings\n    {\n        public static partial class Infrastructure\n        {\n            /// \u003csummary\u003e\n            /// For logging only!\n            /// =\u003e \"Service {0} is required.\"\n            /// \u003c/summary\u003e\n            public static string MissingService(object arg0)\n                =\u003e string.Format(CultureInfo.CurrentCulture, \n                    Strings.GetResourceManager(\"ThisStore.Properties.Resources\").GetString(\"MissingService\"), \n                    arg0);\n        }\n\n        public static partial class Shopping\n        {\n            /// \u003csummary\u003e\n            /// =\u003e \"We cannot ship {0} to {1}.\"\n            /// \u003c/summary\u003e\n            public static string NoShipping(object arg0, object arg1)\n                =\u003e string.Format(CultureInfo.CurrentCulture, \n                    Strings.GetResourceManager(\"ThisStore.Properties.Resources\").GetString(\"NoShipping\"), \n                    arg0, arg1);\n\n            /// \u003csummary\u003e\n            /// =\u003e \"Product is out of stock at this time.\"\n            /// \u003c/summary\u003e\n            public static string OutOfStock\n                =\u003e Strings.GetResourceManager(\"ThisStore.Properties.Resources\").GetString(\"OutOfStock\");\n\n            /// \u003csummary\u003e\n            /// Product available on {date:yyyy-MM}.\n            /// \u003c/summary\u003e\n            public static string AvailableOn(object date) \n                =\u003e string.Format(CultureInfo.CurrentCulture, \n                    Strings.GetResourceManager(\"ThisAssemblyTests.Resources\").GetString(\"WithNamedFormat\").Replace(\"{date:yyyy-MM}\", \"{0}\"), \n                    ((IFormattable)date).ToString(\"yyyy-MM\", CultureInfo.CurrentCulture));\n        }\n    }\n}\n```\n\n## Customizing the generated code\n\nThe following MSBuild properties can be used to customize the generated code:\n\n| Property                | Description                                                                                          |\n|-------------------------|------------------------------------------------------------------------------------------------------|\n| ThisAssemblyNamespace   | Sets the namespace of the generated `ThisAssembly` root class. If not set, it will be in the global namespace. |\n| ThisAssemblyVisibility  | Sets the visibility modifier of the generated `ThisAssembly` root class. If not set, it will be internal. |\n\n\u003c!-- #strings --\u003e\n\u003c!-- src/ThisAssembly.Strings/readme.md#strings --\u003e\n\n## ThisAssembly.Vsix\n\n[![Version](https://img.shields.io/nuget/vpre/ThisAssembly.Vsix.svg?color=royalblue)](https://www.nuget.org/packages/ThisAssembly.Vsix)\n[![Downloads](https://img.shields.io/nuget/dt/ThisAssembly.Vsix.svg?color=green)](https://www.nuget.org/packages/ThisAssembly.Vsix)\n\n\u003c!-- include src/ThisAssembly.Vsix/readme.md#vsix --\u003e\n\u003c!-- #vsix --\u003e\nAllows consuming VSIX manifest properties from code, as well as \nMSBuild project properties from the VSIX manifest. For example:\n\n![](https://raw.githubusercontent.com/devlooped/ThisAssembly/main/img/ThisAssembly.Vsix.png)\n\nIn addition to making the [VSIX manifest metadata](https://learn.microsoft.com/en-us/visualstudio/extensibility/vsix-extension-schema-2-0-reference?view=vs-2022#metadata-element) \nproperties available as constants, the package also provides targets for those properties \nwith sensible defaults from project properties so that the manifest can leverage \n[placeolder syntax](https://learn.microsoft.com/en-us/visualstudio/extensibility/vsix-extension-schema-2-0-reference?view=vs-2022#metadata-element) \nand avoid duplication in the `source.extension.vsixmanifest`:\n\n```xml\n\u003cPackageManifest Version=\"2.0.0\" ...\u003e\n  \u003cMetadata\u003e\n    \u003c!-- You can use the |ProjectName;TargetName| syntax throughout this manifest, BTW --\u003e\n    \u003cIdentity Id=\"|%CurrentProject%;VsixId|\" Version=\"|%CurrentProject%;VsixVersion|\" Language=\"|%CurrentProject%;VsixLanguage|\" Publisher=\"|%CurrentProject%;VsixPublisher|\" /\u003e\n    \u003cDisplayName\u003e|%CurrentProject%;VsixDisplayName|\u003c/DisplayName\u003e\n    \u003cDescription\u003e|%CurrentProject%;VsixDescription|\u003c/Description\u003e\n  \u003c/Metadata\u003e\n  ...\n\u003c/PackageManifest\u003e\n```\n\nThe available properties and their default values are:\n\n| Name              | Default Value                       |\n|-------------------|-------------------------------------|\n| VsixID            | `$(PackageId)` or `$(AssemblyName)` |\n| VsixVersion       | `$(Version)`                        |\n| VsixDisplayName   | `$(Title)`                          |\n| VsixDescription   | `$(Description)`                    |\n| VsixProduct       | `$(Product)`                        |\n| VsixPublisher     | `$(Company)`                        |\n| VsixLanguage      | `$(NeutralLanguage)` or 'en-US'     |\n\nAs shown in the example above, the syntax for using these properties from the `source.extension.vsixmanifest` is \n`|%CurrentProject%;[PROPERTY]|`. This is because the package defines a corresponding target to \nretrieve each of the above properties. You can provide a different value for each property via \nMSBuild as usual, of course.\n\nSince the `$(PackageId)` property can be used as the VSIX ID, the `Pack` target is redefined to \nmean `CreateVsixManifest`, so \"packing\" the VSIX is just a matter of right-clicking the VSIX \nproject and selecting \"Pack\".\n\n\u003c!-- #vsix --\u003e\n\u003c!-- src/ThisAssembly.Vsix/readme.md#vsix --\u003e\n\n\u003c!-- include src/visibility.md --\u003e\n## Customizing the generated code\n\nSet the `$(ThisAssemblyNamespace)` MSBuild property to set the namespace of the \ngenerated `ThisAssembly` root class. Otherwise, it will be generated in the global namespace.\n\nThe generated root `ThisAssembly` class is partial and has no visibility modifier by default, \nmaking it internal by default in C#.\n\nYou can set the `$(ThisAssemblyVisibility)` MSBuild property to `public` to make it public. \nThis will also change all constants to be static readonly properties instead. \n\nDefault:\n```csharp\npartial class ThisAssembly\n{\n    public partial class Constants\n    {\n        public const string Hello = \"World\";\n    }\n}\n```\n\nIn this case, the compiler will inline the constants directly into the consuming code at \nthe call site, which is optimal for performance for the common usage of constants.\n\nPublic:\n```csharp\npublic partial class ThisAssembly\n{\n    public partial class Constants\n    {\n        public static string Hello =\u003e \"World\";\n    }\n}\n```\n\nThis makes it possible for consuming code to remain unchanged and not require \na recompile when the the values of `ThisAssembly` are changed in a referenced assembly.\n\nIf you want to keep the properties as constants, you can instead extend the generated \ncode by defining another partial that can modify its visibility as needed (or add \nnew members). \n\n```csharp\n// makes the generated class public\npublic partial ThisAssembly \n{\n    // Nested classes are always public since the outer class \n    // already limits their visibility\n    partial class Constants \n    {\n        // add some custom constants\n        public const string MyConstant = \"This isn't configurable via MSBuild\";\n\n        // generated code will remain as constants\n    }\n}\n```\n\n\u003c!-- src/visibility.md --\u003e\n\n# Dogfooding\n\n[![CI Version](https://img.shields.io/endpoint?url=https://shields.kzu.app/vpre/Stunts/main\u0026label=nuget.ci\u0026color=brightgreen)](https://pkg.kzu.app/index.json)\n[![Build](https://github.com/devlooped/ThisAssembly/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/devlooped/ThisAssembly/actions)\n\nWe also produce CI packages from branches and pull requests so you can dogfood builds as quickly as they are produced. \n\nThe CI feed is `https://pkg.kzu.app/index.json`. \n\nThe versioning scheme for packages is:\n\n- PR builds: *42.42.42-pr*`[NUMBER]`\n- Branch builds: *42.42.42-*`[BRANCH]`.`[COMMITS]`\n\n\n\u003c!-- include https://github.com/devlooped/sponsors/raw/main/footer.md --\u003e\n# Sponsors \n\n\u003c!-- sponsors.md --\u003e\n[![Clarius Org](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/clarius.png \"Clarius Org\")](https://github.com/clarius)\n[![MFB Technologies, Inc.](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/MFB-Technologies-Inc.png \"MFB Technologies, Inc.\")](https://github.com/MFB-Technologies-Inc)\n[![Torutek](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/torutek-gh.png \"Torutek\")](https://github.com/torutek-gh)\n[![DRIVE.NET, Inc.](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/drivenet.png \"DRIVE.NET, Inc.\")](https://github.com/drivenet)\n[![Keith Pickford](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/Keflon.png \"Keith Pickford\")](https://github.com/Keflon)\n[![Thomas Bolon](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/tbolon.png \"Thomas Bolon\")](https://github.com/tbolon)\n[![Kori Francis](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/kfrancis.png \"Kori Francis\")](https://github.com/kfrancis)\n[![Toni Wenzel](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/twenzel.png \"Toni Wenzel\")](https://github.com/twenzel)\n[![Uno Platform](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/unoplatform.png \"Uno Platform\")](https://github.com/unoplatform)\n[![Dan Siegel](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/dansiegel.png \"Dan Siegel\")](https://github.com/dansiegel)\n[![Reuben Swartz](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/rbnswartz.png \"Reuben Swartz\")](https://github.com/rbnswartz)\n[![Jacob Foshee](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/jfoshee.png \"Jacob Foshee\")](https://github.com/jfoshee)\n[![](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/Mrxx99.png \"\")](https://github.com/Mrxx99)\n[![Eric Johnson](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/eajhnsn1.png \"Eric Johnson\")](https://github.com/eajhnsn1)\n[![David JENNI](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/davidjenni.png \"David JENNI\")](https://github.com/davidjenni)\n[![Jonathan ](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/Jonathan-Hickey.png \"Jonathan \")](https://github.com/Jonathan-Hickey)\n[![Charley Wu](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/akunzai.png \"Charley Wu\")](https://github.com/akunzai)\n[![Ken Bonny](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/KenBonny.png \"Ken Bonny\")](https://github.com/KenBonny)\n[![Simon Cropp](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/SimonCropp.png \"Simon Cropp\")](https://github.com/SimonCropp)\n[![agileworks-eu](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/agileworks-eu.png \"agileworks-eu\")](https://github.com/agileworks-eu)\n[![sorahex](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/sorahex.png \"sorahex\")](https://github.com/sorahex)\n[![Zheyu Shen](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/arsdragonfly.png \"Zheyu Shen\")](https://github.com/arsdragonfly)\n[![Vezel](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/vezel-dev.png \"Vezel\")](https://github.com/vezel-dev)\n[![ChilliCream](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/ChilliCream.png \"ChilliCream\")](https://github.com/ChilliCream)\n[![4OTC](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/4OTC.png \"4OTC\")](https://github.com/4OTC)\n[![Vincent Limo](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/v-limo.png \"Vincent Limo\")](https://github.com/v-limo)\n[![Jordan S. Jones](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/jordansjones.png \"Jordan S. Jones\")](https://github.com/jordansjones)\n[![domischell](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/DominicSchell.png \"domischell\")](https://github.com/DominicSchell)\n[![Mauricio Scheffer](https://raw.githubusercontent.com/devlooped/sponsors/main/.github/avatars/mausch.png \"Mauricio Scheffer\")](https://github.com/mausch)\n\n\n\u003c!-- sponsors.md --\u003e\n\n[![Sponsor this project](https://raw.githubusercontent.com/devlooped/sponsors/main/sponsor.png \"Sponsor this project\")](https://github.com/sponsors/devlooped)\n\u0026nbsp;\n\n[Learn more about GitHub Sponsors](https://github.com/sponsors)\n\n\u003c!-- https://github.com/devlooped/sponsors/raw/main/footer.md --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevlooped%2Fthisassembly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdevlooped%2Fthisassembly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdevlooped%2Fthisassembly/lists"}