Communityコーディング&開発github.com

dotnet-project-structure

最新の.NETプロジェクト構造(.slnxソリューション形式、Directory.Build.props、一元管理パッケージ管理、SourceLink、RELEASE_NOTES.mdによるバージョン管理、global.jsonによるSDK固定)を提供します。

dotnet-project-structure とは?

このスキルは、.NET開発者向けに最新のベストプラクティスに基づいたプロジェクト構造のセットアップと構成を自動化・支援します。主な機能は、.slnx形式のソリューションファイルの作成と移行、Directory.Build.propsによる一元化されたビルドプロパティの設定、中央パッケージ管理(CPM)によるNuGetパッケージバージョンの一元管理、SourceLinkの有効化によるデバッグ体験の向上、RELEASE_NOTES.mdを用いた自動バージョン管理スクリプトの提供、そしてglobal.jsonによるSDKバージョンの固定です。これにより、開発チーム全体で一貫性のあるビルド環境と効率的な開発ワークフローを実現できます。サポート対象は主に.NET 9以降(.slnx形式は.NET 9.0.200以上、.NET 10+ではデフォルト)、Visual Studio 17.13以上、MSBuild Build Tools 17.13以上です。このスキルは、コマンドラインやCI/CDパイプラインと統合しやすく、GitHub Actionsの例も含まれています。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Aaronontheweb/dotnet-skills/tree/main/skills/project-structure

Installed? Explore more コーディング&開発 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

.NET プロジェクト構造とビルド構成

このスキルを使用するタイミング

以下の場合にこのスキルを使用します。

  • 最新のベストプラクティスで新しい.NETソリューションをセットアップするとき
  • 複数のプロジェクトにわたるビルドプロパティを一元管理するとき
  • 中央パッケージバージョン管理を実装するとき
  • デバッグおよびNuGetパッケージ用のSourceLinkを設定するとき
  • リリースノートを使用したバージョン管理を自動化するとき
  • 一貫性のあるビルドのためにSDKバージョンを固定するとき

関連スキル

  • dotnet-local-tools - dotnet-tools.jsonを使用したローカル.NETツールの管理
  • microsoft-extensions-configuration - 構成検証パターン

ソリューションファイル形式 (.slnx)

.slnx形式は、.NET 9で導入された最新のXMLベースのソリューションファイル形式です。従来の.sln形式を置き換えます。

従来の .sln に対する利点

項目.sln (レガシー).slnx (モダン)
形式独自テキスト形式標準XML
可読性GUID、難解な構文クリーンで人間が読める
バージョン管理差分/マージが難しい差分/マージが簡単
編集IDE必須任意のテキストエディタで可

バージョン要件

ツール最小バージョン
.NET SDK9.0.200
Visual Studio17.13
MSBuildVisual Studio Build Tools 17.13

注: .NET 10以降、dotnet new slnはデフォルトで.slnxファイルを作成します。.NET 9では、明示的に移行するか、形式を指定する必要があります。

例: .slnx ファイル

<Solution>
  <Folder Name="/build/">
    <File Path="Directory.Build.props" />
    <File Path="Directory.Packages.props" />
    <File Path="global.json" />
    <File Path="NuGet.Config" />
    <File Path="README.md" />
  </Folder>
  <Folder Name="/src/">
    <Project Path="src/MyApp/MyApp.csproj" />
    <Project Path="src/MyApp.Core/MyApp.Core.csproj" />
  </Folder>
  <Folder Name="/tests/">
    <Project Path="tests/MyApp.Tests/MyApp.Tests.csproj" />
  </Folder>
</Solution>

.sln から .slnx への移行

dotnet sln migrate コマンドを使用して既存のソリューションを変換します。

# 特定のソリューションファイルを移行
dotnet sln MySolution.sln migrate

# または、ディレクトリに .sln ファイルが1つしかない場合は、以下を実行:
dotnet sln migrate

重要: 同じリポジトリに .sln と .slnx の両方のファイルを保持しないでください。自動ソリューション検出に問題が発生し、同期の問題を引き起こす可能性があります。移行後は、古い .sln ファイルを削除してください。

Visual Studio で移行することもできます。

  1. ソリューションを開く
  2. ソリューションエクスプローラーでソリューションを選択
  3. ファイル > ソリューションの名前を付けて保存... に移動
  4. "ファイルの種類" を Xml ソリューションファイル (*.slnx) に変更

新しい .slnx ソリューションの作成

# .NET 10+: デフォルトで .slnx を作成
dotnet new sln --name MySolution

# .NET 9: 明示的に形式を指定
dotnet new sln --name MySolution --format slnx

# プロジェクトの追加 (両方の形式で同じように動作)
dotnet sln add src/MyApp/MyApp.csproj

推奨事項

.NET 9.0.200 以降を使用している場合は、ソリューションを .slnx に移行してください。 利点は非常に大きいです。

  • マージ競合が劇的に減少(ランダムなGUIDが変更されない)
  • 人間が読みやすく、任意のテキストエディタで編集可能
  • 最新の .csproj 形式と一貫性がある
  • プルリクエストでの差分確認/レビュー体験が向上

Directory.Build.props

Directory.Build.props は、ディレクトリツリー内のすべてのプロジェクトに適用される一元化されたビルド構成を提供します。ソリューションルートに配置します。

完全な例

<Project>
  <!-- メタデータ -->
  <PropertyGroup>
    <Authors>Your Team</Authors>
    <Company>Your Company</Company>
    <!-- 動的な著作権年 - 自動更新 -->
    <Copyright>Copyright © 2020-$([System.DateTime]::Now.Year) Your Company</Copyright>
    <Product>Your Product</Product>
    <PackageProjectUrl>https://github.com/yourorg/yourrepo</PackageProjectUrl>
    <RepositoryUrl>https://github.com/yourorg/yourrepo</RepositoryUrl>
    <PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
    <PackageTags>your;tags;here</PackageTags>
  </PropertyGroup>

  <!-- C# 言語設定 -->
  <PropertyGroup>
    <LangVersion>latest</LangVersion>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
    <NoWarn>$(NoWarn);CS1591</NoWarn> <!-- XML コメントの欠落 -->
  </PropertyGroup>

  <!-- バージョン管理 -->
  <PropertyGroup>
    <VersionPrefix>1.0.0</VersionPrefix>
    <PackageReleaseNotes>See RELEASE_NOTES.md</PackageReleaseNotes>
  </PropertyGroup>

  <!-- ターゲットフレームワーク定義 (再利用可能なプロパティ) -->
  <PropertyGroup>
    <NetStandardLibVersion>netstandard2.0</NetStandardLibVersion>
    <NetLibVersion>net8.0</NetLibVersion>
    <NetTestVersion>net9.0</NetTestVersion>
  </PropertyGroup>

  <!-- SourceLink 設定 -->
  <PropertyGroup>
    <PublishRepositoryUrl>true</PublishRepositoryUrl>
    <EmbedUntrackedSources>true</EmbedUntrackedSources>
    <IncludeSymbols>true</IncludeSymbols>
    <SymbolPackageFormat>snupkg</SymbolPackageFormat>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
  </ItemGroup>

  <!-- NuGet パッケージアセット -->
  <ItemGroup>
    <None Include="$(MSBuildThisFileDirectory)logo.png" Pack="true" PackagePath="\" />
    <None Include="$(MSBuildThisFileDirectory)README.md" Pack="true" PackagePath="\" />
  </ItemGroup>

  <PropertyGroup>
    <PackageIcon>logo.png</PackageIcon>
    <PackageReadmeFile>README.md</PackageReadmeFile>
  </PropertyGroup>

  <!-- グローバル using ステートメント -->
  <ItemGroup>
    <Using Include="System.Collections.Immutable" />
  </ItemGroup>
</Project>

主要なパターン

動的な著作権年

<Copyright>Copyright © 2020-$([System.DateTime]::Now.Year) Your Company</Copyright>

MSBuild プロパティ関数を使用して、ビルド時に現在の年を挿入します。手動更新は不要です。

再利用可能なターゲットフレームワークプロパティ

ターゲットフレームワークを一度定義し、あらゆる場所で参照します:

<!-- Directory.Build.props 内 -->
<PropertyGroup>
  <NetLibVersion>net8.0</NetLibVersion>
  <NetTestVersion>net9.0</NetTestVersion>
</PropertyGroup>

<!-- MyApp.csproj 内 -->
<PropertyGroup>
  <TargetFramework>$(NetLibVersion)</TargetFramework>
</PropertyGroup>

<!-- MyApp.Tests.csproj 内 -->
<PropertyGroup>
  <TargetFramework>$(NetTestVersion)</TargetFramework>
</PropertyGroup>

NuGet パッケージ用 SourceLink

SourceLink は NuGet パッケージのステップスルーデバッグを可能にします:

<PropertyGroup>
  <PublishRepositoryUrl>true</PublishRepositoryUrl>
  <EmbedUntrackedSources>true</EmbedUntrackedSources>
  <IncludeSymbols>true</IncludeSymbols>
  <SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>

<ItemGroup>
  <!-- ソース管理に適したプロバイダーを選択 -->
  <PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
  <!-- または: Microsoft.SourceLink.AzureRepos.Git -->
  <!-- または: Microsoft.SourceLink.GitLab -->
  <!-- または: Microsoft.SourceLink.Bitbucket.Git -->
</ItemGroup>

Directory.Packages.props - 中央パッケージ管理

中央パッケージ管理 (CPM) は、すべての NuGet パッケージバージョンの単一の信頼できる情報源を提供します。

設定

<Project>
  <PropertyGroup>
    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
  </PropertyGroup>

  <!-- 関連パッケージのバージョン変数を定義 -->
  <PropertyGroup>
    <AkkaVersion>1.5.35</AkkaVersion>
    <AspireVersion>9.1.0</AspireVersion>
  </PropertyGroup>

  <!-- アプリケーション依存関係 -->
  <ItemGroup Label="アプリ依存関係">
    <PackageVersion Include="Akka" Version="$(AkkaVersion)" />
    <PackageVersion Include="Akka.Cluster" Version="$(AkkaVersion)" />
    <PackageVersion Include="Akka.Persistence" Version="$(AkkaVersion)" />
    <PackageVersion Include="Microsoft.Extensions.Hosting" Version="9.0.0" />
  </ItemGroup>

  <!-- ビルド/ツール依存関係 -->
  <ItemGroup Label="ビルド依存関係">
    <PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
  </ItemGroup>

  <!-- テスト依存関係 -->
  <ItemGroup Label="テスト依存関係">
    <PackageVersion Include="xunit" Version="2.9.3" />
    <PackageVersion Include="xunit.runner.visualstudio" Version="3.0.1" />
    <PackageVersion Include="FluentAssertions" Version="7.0.0" />
    <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
    <PackageVersion Include="coverlet.collector" Version="6.0.3" />
  </ItemGroup>
</Project>

パッケージの使用 (バージョン不要)

<!-- MyApp.csproj 内 -->
<ItemGroup>
  <PackageReference Include="Akka" />
  <PackageReference Include="Akka.Cluster" />
  <PackageReference Include="Microsoft.Extensions.Hosting" />
</ItemGroup>

<!-- MyApp.Tests.csproj 内 -->
<ItemGroup>
  <PackageReference Include="xunit" />
  <PackageReference Include="FluentAssertions" />
  <PackageReference Include="Microsoft.NET.Test.Sdk" />
</ItemGroup>

利点

  1. 単一の信頼できる情報源 - すべてのバージョンが1つのファイルに
  2. バージョンのずれなし - すべてのプロジェクトが同じバージョンを使用
  3. 簡単な更新 - 一度変更すれば、すべてに適用
  4. グループ化されたパッケージ - 関連パッケージのバージョン変数 (例: すべての Akka パッケージ)

global.json - SDKバージョンの固定

すべての環境で一貫性のあるビルドのために .NET SDK バージョンを固定します。

{
  "sdk": {
    "version": "9.0.200",
    "rollForward": "latestFeature"
  }
}

ロールフォワードポリシー

ポリシー動作
disable正確なバージョンが必要
patch同じメジャー.マイナー、最新パッチ
feature同じメジャー、最新マイナー.パッチ
latestFeature同じメジャー、最新機能バンド
minor同じメジャー、最新マイナー
latestMinor同じメジャー、最新マイナー
major最新 SDK (非推奨)

推奨: latestFeature - 同じ機能バンド内のパッチ更新を許可します。


RELEASE_NOTES.md を使用したバージョン管理

リリースノートの形式

#### 1.2.0 2025年1月15日 ####

- 新しい機能Xを追加
- Yのバグを修正
- Zのパフォーマンスを改善

#### 1.1.0 2024年12月10日 ####

- 機能A、B、Cを含む初期リリース

解析スクリプト (getReleaseNotes.ps1)

function Get-ReleaseNotes {
    param (
        [Parameter(Mandatory=$true)]
        [string]$MarkdownFile
    )

    $content = Get-Content -Path $MarkdownFile -Raw
    $sections = $content -split "####"

    $result = [PSCustomObject]@{
        Version      = $null
        Date         = $null
        ReleaseNotes = $null
    }

    if ($sections.Count -ge 3) {
        $header = $sections[1].Trim()
        $releaseNotes = $sections[2].Trim()

        $headerParts = $header -split " ", 2
        if ($headerParts.Count -eq 2) {
            $result.Version = $headerParts[0]
            $result.Date = $headerParts[1]
        }

        $result.ReleaseNotes = $releaseNotes
    }

    return $result
}

バージョン更新スクリプト (bumpVersion.ps1)

function UpdateVersionAndReleaseNotes {
    param (
        [Parameter(Mandatory=$true)]
        [PSCustomObject]$ReleaseNotesResult,
        [Parameter(Mandatory=$true)]
        [string]$XmlFilePath
    )

    $xmlContent = New-Object XML
    $xmlContent.Load($XmlFilePath)

    # VersionPrefix を更新
    $versionElement = $xmlContent.SelectSingleNode("//VersionPrefix")
    $versionElement.InnerText = $ReleaseNotesResult.Version

    # PackageReleaseNotes を更新
    $notesElement = $xmlContent.SelectSingleNode("//PackageReleaseNotes")
    $notesElement.InnerText = $ReleaseNotesResult.ReleaseNotes

    $xmlContent.Save($XmlFilePath)
}

ビルドスクリプト (build.ps1)

# ヘルパースクリプトを読み込む
. "$PSScriptRoot\scripts\getReleaseNotes.ps1"
. "$PSScriptRoot\scripts\bumpVersion.ps1"

# リリースノートを解析し、Directory.Build.props を更新
$releaseNotes = Get-ReleaseNotes -MarkdownFile (Join-Path -Path $PSScriptRoot -ChildPath "RELEASE_NOTES.md")
UpdateVersionAndReleaseNotes -ReleaseNotesResult $releaseNotes -XmlFilePath (Join-Path -Path $PSScriptRoot -ChildPath "Directory.Build.props")

Write-Output "バージョン $($releaseNotes.Version) に更新しました"

CI/CD 統合

# GitHub Actions の例
- name: リリースノートからバージョンを更新
  shell: pwsh
  run: ./build.ps1

- name: ビルド
  run: dotnet build -c Release

- name: タグバージョンでパック
  run: dotnet pack -c Release /p:PackageVersion=${{ github.ref_name }}

- name: NuGet にプッシュ
  run: dotnet nuget push **/*.nupkg --api-key ${{ secrets.NUGET_API_KEY }} --source https://api.nuget.org/v3/index.json

NuGet.Config

NuGet ソースと動作を構成します:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <solution>
    <add key="disableSourceControlIntegration" value="true" />
  </solution>

  <packageSources>
    <clear />
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
    <!-- 必要に応じてプライベートフィードを追加 -->
    <!-- <add key="MyCompany" value="https://pkgs.dev.azure.com/myorg/_packaging/myfeed/nuget/v3/index.json" /> -->
  </packageSources>
</configuration>

主要な設定:

  • <clear /> - 再現可能なビルドのために継承/デフォルトソースを削除
  • disableSourceControlIntegration - TFS/Git 統合の問題を防ぐ

完全なプロジェクト構造

MySolution/
├── .config/
│   └── dotnet-tools.json           # ローカル .NET ツール
├── .github/
│   └── workflows/
│       ├── pr-validation.yml       # PR チェック
│       └── release.yml             # NuGet への公開
├── scripts/
│   ├── getReleaseNotes.ps1         # RELEASE_NOTES.md の解析
│   └── bumpVersion.ps1             # Directory.Build.props の更新
├── src/
│   ├── MyApp/
│   │   └── MyApp.csproj
│   └── MyApp.Core/
│       └── MyApp.Core.csproj
├── tests/
│   └── MyApp.Tests/
│       └── MyApp.Tests.csproj
├── Directory.Build.props           # 一元化されたビルド構成
├── Directory.Packages.props        # 中央パッケージ管理
├── MySolution.slnx                 # ソリューションファイル
├── global.json                     # SDK バージョンの固定
├── NuGet.Config                    # NuGet ソース設定
├── RELEASE_NOTES.md                # バージョン履歴
├── README.md                       # プロジェクトドキュメント
└── logo.png                        # NuGet パッケージアイコン

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

akka-hosting-actor-patterns

Patterns for building entity actors with Akka.Hosting - GenericChildPerEntityParent, message extractors, cluster sharding abstraction, akka-reminders, and ITimeProvider. Supports both local testing and clustered production modes.

akka-net-aspire-configuration

Configure Akka.NET with .NET Aspire for local development and production deployments. Covers actor system setup, clustering, persistence, Akka.Management integration, and Aspire orchestration patterns.

akka-net-best-practices

Critical Akka.NET best practices including EventStream vs DistributedPubSub, supervision strategies, error handling, Props vs DependencyResolver, work distribution patterns, and cluster/local mode abstractions for testability.

akka-net-management

Akka.Management for cluster bootstrapping, service discovery (Kubernetes, Azure, Config), health checks, and dynamic cluster formation without static seed nodes.

akka-net-testing-patterns

Write unit and integration tests for Akka.NET actors using modern Akka.Hosting.TestKit patterns. Covers dependency injection, TestProbes, persistence testing, and actor interaction verification. Includes guidance on when to use traditional TestKit.

api-design

Design stable, compatible public APIs using extend-only design principles. Manage API compatibility, wire compatibility, and versioning for NuGet packages and distributed systems.

aspire-configuration

Configure Aspire AppHost to emit explicit app config via environment variables; keep app code free of Aspire clients and service discovery.

aspire-integration-testing

Write integration tests using .NET Aspire

aspire-service-defaults

Create a shared ServiceDefaults project for Aspire applications. Centralizes OpenTelemetry, health checks, resilience, and service discovery configuration across all services.

crap-analysis

Analyze code coverage and CRAP (Change Risk Anti-Patterns) scores to identify high-risk code. Use OpenCover format with ReportGenerator for Risk Hotspots showing cyclomatic complexity and untested code paths.

csharp-concurrency-patterns

Choosing the right concurrency abstraction in .NET - from async/await for I/O to Channels for producer/consumer to Akka.NET for stateful entity management. Avoid locks and manual synchronization unless absolutely necessary.

database-performance

Database access patterns for performance. Separate read/write models, avoid N+1 queries, use AsNoTracking, apply row limits, and never do application-side joins. Works with EF Core and Dapper.

dependency-injection-patterns

Organize DI registrations using IServiceCollection extension methods. Group related services into composable Add* methods for clean Program.cs and reusable configuration in tests.

dotnet-devcert-trust

Diagnose and fix .NET HTTPS dev certificate trust issues on Linux. Covers the full certificate lifecycle from generation to system CA bundle inclusion, with distro-specific guidance for Ubuntu, Fedora, Arch, and WSL2.

dotnet-local-tools

Managing local .NET tools with dotnet-tools.json for consistent tooling across development environments and CI/CD pipelines.

dotnet-slopwatch

Use Slopwatch to detect LLM reward hacking in .NET code changes. Run after every code modification to catch disabled tests, suppressed warnings, empty catch blocks, and other shortcuts that mask real problems.

efcore-patterns

Entity Framework Core best practices including NoTracking by default, query splitting for navigation collections, migration management, dedicated migration services, and common pitfalls to avoid.

ilspy-decompile

Understand implementation details of .NET code by decompiling assemblies. Use when you want to see how a .NET API works internally, inspect NuGet package source, view framework implementation, or understand compiled .NET binaries.

mailpit-integration

Test email sending locally using Mailpit with .NET Aspire. Captures all outgoing emails without sending them. View rendered HTML, inspect headers, and verify delivery in integration tests.

marketplace-publishing

Workflow for publishing skills and agents to the dotnet-skills Claude Code marketplace. Covers adding new content, updating plugin.json, validation, and release tagging.

関連スキル