How to Manage Assembly Information Across Multiple Projects

How to Manage Assembly Information Across Multiple Projects

Managing assembly information consistently across multiple projects is essential for reliable versioning, clear metadata, and smooth deployment. This guide shows a practical, scalable approach for .NET projects (the principles apply to other ecosystems) that covers versioning strategies, centralization techniques, automation in CI/CD, and troubleshooting.

Why centralize assembly information

  • Clarity: Single source of truth for version, company, product, and other metadata.
  • Consistency: Prevents mismatched versions or duplicate identifiers across assemblies.
  • Automation-friendly: Easier to integrate with build servers and release pipelines.

Key fields to manage

  • AssemblyVersion: Used by the runtime for binding. Breaking changes require major/minor updates.
  • AssemblyFileVersion: Informational; shown in file properties, can change on every build.
  • AssemblyInformationalVersion: Human-readable version (semver + build metadata).
  • Company/Product/Description/Trademark/Culture: Descriptive metadata useful for support and tracking.

Strategy choices (pick one)

  1. Strict SemVer for AssemblyVersion: Update AssemblyVersion only for breaking API changes; use FileVersion for builds.
  2. Synchronized Versions: Keep AssemblyVersion and FileVersion aligned and update both per release.
  3. Auto-increment Builds: Keep AssemblyVersion stable; auto-increment FileVersion or InformationalVersion with CI build number.

Choose the approach matching your compatibility guarantees and package ecosystem (NuGet, internal deployment).

Centralization techniques

1) Shared props/targets (recommended for SDK-style .csproj)
  • Create a Directory.Build.props or shared .props file at a repo root:

    xml

    <Project> <PropertyGroup> <Company>Contoso</Company> <Product>Contoso.Lib</Product> <AssemblyVersion>1.2.0.0</AssemblyVersion> <FileVersion>1.2.0.0</FileVersion> <InformationalVersion>1.2.0</InformationalVersion> </PropertyGroup> </Project>
  • Projects automatically import these values, ensuring consistency.
2) Nerdbank.GitVersioning or GitVersion
  • Use Git-based versioning tools to generate versions from commit history/branches.
  • Configure the tool at repo root; it emits version info during build without manual edits.
  • Works well for multi-repo monorepos or branch-based release workflows.
3) Props per solution or per-component
  • For partial sharing, place props in subfolders and import from specific projects to group versions by component.
4) Source-generated AssemblyInfo
  • Use the SDK project properties (GenerateAssemblyInfo) and set version-related MSBuild properties instead of maintaining AssemblyInfo.cs files.

Automation in CI/CD

  1. Inject build metadata: In CI, append build number or commit SHA to InformationalVersion.
    • Example: 1.2.0+build.20260206.45 or 1.2.0+sha.abcdef
  2. Update package metadata: Ensure NuGet pack uses the same version properties.
  3. Artifact stamping: Use the same shared props or a build step that writes a generated AssemblyInfo.cs into the build workspace.
  4. Release pipeline: Validate versions (no duplicates), tag the repository with the released version, and publish artifacts with matching metadata.

Example GitHub Actions step to set InformationalVersion:

yaml

- name: Set version run: | echo “##[set-output name=version;]\((git describe --tags --abbrev=0)-build.\)GITHUB_RUN_NUMBER”

Handling multi-repo scenarios

  • Use a centralized package or repo that contains the shared props and add it as a submodule or fetch during CI.
  • Alternatively, publish a NuGet package containing MSBuild props/targets consumed by other repos.

Best practices and checklist

  • Single source of truth: Prefer Directory.Build.props or an MSBuild props package.
  • Use InformationalVersion for build metadata and avoid changing AssemblyVersion frequently.
  • Automate version generation in CI to avoid manual mistakes.
  • Tag releases in source control to enable reproducible builds.
  • Test binding redirects when AssemblyVersion changes to avoid runtime conflicts.
  • Document the chosen strategy in your CONTRIBUTING or developer docs.

Troubleshooting

  • Mismatched runtime versions: verify AssemblyVersion across dependencies or add binding redirects.
  • Unexpected file version: ensure no AssemblyInfo.cs files override MSBuild properties; set GenerateAssemblyInfo accordingly.
  • CI showing different version than local build: check CI inject steps and ensure it uses the same shared props or version tool.

Quick migration plan (3 steps)

  1. Add a Directory.Build.props defining company/product and default versions.
  2. Remove individual AssemblyInfo.cs files (or set GenerateAssemblyInfo) and confirm projects inherit props.
  3. Add CI step to set InformationalVersion with build metadata and tag releases.

Following these steps will keep assembly metadata consistent, make releases reproducible, and reduce versioning errors across projects.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *