Skip to content

MS_VSSolutionStructure

nishi_74322014 edited this page Sep 1, 2026 · 1 revision

VSソリューション プロジェクトの構成検討

概要

Visual Studio の、「ソリューション」・「プロジェクト」の構成を検討する際の
ポイントについて説明する。

ソリューション・プロジェクト

Visual Studio では、開発するプログラムを、
ソリューション・プロジェクトという単位で管理する。

  • 1つのプログラムは、1-複数のアセンブリ(EXE や DLL ファイル)から
    構成される場合がある。

  • 1つの Web サイト・Web アプリケーションも、
    1-複数のアセンブリやコンテンツ ファイルから構成される。

  • また、各アセンブリをコンピュータにインストールするための
    「セットアップ プログラム」・「Web セットアップ プログラム」などがある。

補足(3 つの単位の対応関係): 混乱しやすいので先に整理する。

ソリューション(*.sln)      … 1 つ以上のプロジェクトを束ねる「作業単位」
  └ プロジェクト(*.csproj) … 1 つのアセンブリを作る「ビルド単位」
       └ アセンブリ(*.dll) … 1 つの「配置・バージョン管理単位」

原則 1 プロジェクト = 1 アセンブリであり、
ソリューションはビルドはするが、成果物そのものではない。
.NETアセンブリ も併せて参照。

プロジェクト

  • プロジェクトのビルドに関する構成情報を保持している。
  • 1つのアセンブリを作成するには、1つの「プロジェクト」が必要になる。
  • 1つの基本的なプロジェクトは1つのアセンブリを出力する(EXE、DLL)。

プロジェクト ファイル

  • *.csproj(C# 用)、*.vbproj(VB 用)などの拡張子を持つ。

  • Windows アプリケーションの VB プロジェクトのプロパティの例

    • アプリケーション

      • アセンブリ名
      • 名前空間
      • アプリケーションの種類
      • アイコン
      • スタートアップ フォーム
      • フレームワーク
      • プロパティ
      • ,etc.
    • コンパイル

      • ビルド出力パス
      • 詳細コンパイル オプション
      • Option Explicit,Strict,Compare
      • 警告・エラーの表示
      • ,etc.
    • デバッグ
      デバッグ時の動作の設定をする。

      • スタートアップ
      • コマンドライン引数
      • ,etc.
    • 参照
      アセンブリや COM コンポーネントなど、
      プロジェクトで使用するコンポーネントの参照設定を設定する。

    • リソース
      プロジェクトのリソースを設定する。

      • 文字列
      • イメージ
      • アイコン
      • オーディオ
      • ファイル
      • ,etc.
    • 設定
      app.config のユーザ セッティング情報を設定する。

    • 署名
      アセンブリに厳密名などのアセンブリ署名をしたりする。

    • セキュリティ、発行
      ClickOnce アプリケーションで使用する設定をする。

補足: これらの設定は、いずれも MSBuild の
プロパティとして .csproj に書かれる。
GUI はその編集画面に過ぎない。
SDK 形式のプロジェクトでは .csproj が非常に短くなったため、
直接編集する方が速い場面も多い。

分割の意味

  • モジュール単位の変更
  • 配布単位の変更(アセンブリでの配布)

ソリューション

  • 全体のビルドに関する構成情報を保持している。

  • 複数のアセンブリから構成されるアプリケーションを作成できる。

  • このような構成を行う場合、以下の2通りの方法がある。

    • 複数のアセンブリをプロジェクトでまとめる(バイナリ参照)。
    • 複数のプロジェクトをソリューションでまとめる(プロジェクト参照)。

ソリューション ファイル

  • *.sln の拡張子を持つ。

  • ソリューションのプロパティの例

補足(最新化): .NET SDK 10 以降では、
*.slnx という新しい XML 形式のソリューション ファイルが導入された。
従来の .sln は独自形式で GUID が多く、
マージ コンフリクトが起きやすいという問題があったが、
.slnx はプロジェクトのパスを列挙するだけの素直な XML になっている。

<Solution>
  <Project Path="src/App/App.csproj" />
  <Project Path="src/Lib/Lib.csproj" />
</Solution>

分割の意味

  • ビルド単位の変更
  • 配布単位の変更(MSI での配布)

分割のメリット・デメリット

一般的に小規模開発の場合は分割を少なくして、大規模開発の場合に分割を検討する。

トレードオフ

メリット

  • 管理が容易になる。

  • 開発作業の分担が可能になる。

  • 部品化等により差し替えが容易になる。

  • 修正箇所毎、ビルド範囲を絞る事ができる。

  • アセンブリや MSI での配布が容易。

  • プロセス、アプリケーション ドメイン分割により、
    障害範囲を少なくできる。

デメリット

  • 管理が煩雑になる。

  • 開発作業の分担ができなくなる。

  • 部品化等により差し替えができなくなる。

  • 修正箇所毎、ビルド範囲を絞る事ができなくなる。

  • 複数のアセンブリや MSI を
    組み合わせた配布が必要になる。

  • プロセス、アプリケーション ドメイン分割により、
    プロセス間通信が必要になる。

補足(この表の読み方): メリットとデメリットが
同じ項目の裏返しになっている点が要点である。
原文は「分割しない場合のデメリット」を並べているのではなく、
分割しすぎた場合のデメリットを並べていると読むのが正しい。

分割しない ◀──────────────────▶ 分割しすぎ
 ・ビルドが遅い                    ・管理が煩雑
 ・差し替えできない                ・参照関係が追えない
 ・分担しにくい                    ・ビルド順序が複雑

補足(実務上の目安): 現在の一般的な指針は
**「プロジェクトは少ないほど良い」**である。

  • プロジェクト数はビルド時間に直結する(1 プロジェクト = 1 コンパイル)
  • アセンブリ境界は実行時のコストでもある(型のロード、JIT)
  • 「レイヤごとにプロジェクトを分ける」だけでは設計上の意味が薄い
    (フォルダと internal で足りることが多い)

分けるべき明確な理由があるときにだけ分ける、というのが原則。

分ける理由 例
別々に配布する NuGet パッケージにする、他システムへ提供する
参照の向きを強制したい ドメイン層がインフラ層を参照しないことを保証する
ターゲットが違う 一方は netstandard2.0、他方は net8.0
テストプロジェクト 本体と一緒に配布しない

補足(最新化): アプリケーション ドメインは
.NET Core 以降存在しない
(作成できない)。
以下は .NET Framework + IIS 前提の話である。

.NET Framework .NET(Core 系)
分離の単位 AppDomain(1 プロセス内で複数) プロセス
アセンブリのアンロード AppDomain 単位で可能 AssemblyLoadContext で可能
Web の分離 IIS のアプリケーション プール + AppDomain プロセス(Kestrel)単位

ASP.NET Core では 1 アプリ = 1 プロセスが基本であり、
分離はコンテナやアプリケーション プールの粒度で考えることになる。

異なるアプリケーション ドメインに画面遷移する方法

  • Server.Transfer は不可能。
  • Response.Redirect, Link などの Get メソッドは可能。
  • クロスページ ポストバックなどの POST メソッドは可能。

異なるアプリケーション ドメインと情報共有する方法

以下の状態管理技術は、異なるアプリケーション ドメインと情報共有できない。

  • Application オブジェクト

  • 静的変数

  • Cache オブジェクト

  • Session オブジェクト

  • その他

    • ViewState は同一 WebForm 画面内でのみ有用。
    • HttpContext は、Server.Transfer 画面遷移の間で有用

以下の状態管理技術は、異なるアプリケーション ドメインと情報共有できる。

  • QueryString
  • Cookie
  • Hidden
  • Cookie 認証チケット
    ASP.NET2.0 から ASP.NET の Forms 認証の認証チケットを
    • 複数のサイト間で共有する仕組みが用意され、
    • 複数のサイト間で利用できるようになった。

各状態管理技術については、コチラを参照。

補足(この分類の本質): 共有できるものとできないものの違いは、
どこに状態が置かれているかで決まる。

【共有できない】サーバのメモリ(プロセス内)に置く
   Application / 静的変数 / Cache / Session(InProc)

【共有できる】クライアントが持ち運ぶ
   QueryString / Cookie / Hidden / 認証チケット

したがって Session も「外に出せば」共有できる。
SQL Server セッション ステート、Redis(分散キャッシュ)を
使えばプロセスをまたげる。
これは .NET CoreのDockerコンテナ化 で述べた
「コンテナは複数インスタンスに増えるので状態を外出しする」
という話とまったく同じ構図である。

参照設定の選択

プロジェクト参照

  • プロジェクトに対して参照設定を行う。

  • ビルド順も自動的に管理され、バージョンの不一致などが起こり難く使い易い。

  • 参照先のプロジェクトの変更・差し替えが容易なので、
    FIX していないモジュールに対してはプロジェクト参照を使用する。

バイナリ参照

  • アセンブリに対して参照設定を行う。

  • 参照先のバイナリの変更・差し替えが面倒なので、
    FIX したモジュールに対してはバイナリ参照を使用する。

補足(現在は 3 つ目の選択肢がある): 「FIX したかどうか」で
使い分けるという原文の整理は妥当だが、
現在は NuGet の PackageReference が
バイナリ参照の上位互換として使える。

方式 向く場面 依存の解決
プロジェクト参照 同じソリューション内。同時に開発する ビルド順が自動
バイナリ参照(HintPath) 手元の DLL を直接指す 手動(推移的依存も自分で)
PackageReference 別リリース サイクルの共通部品 自動(推移的依存も解決)

バイナリ参照は推移的依存を自分で管理する必要があるため、
現在は NuGet 化するのが素直である
(社内なら NuGet プライベート・リポジトリ)。

Web アプリケーション、Web サイト

関係

1 Web アプリ・サイト ≒ 1 IIS アプリ

  • 1つの Web アプリケーション・Web サイトは、
    1つの IIS のアプリケーションと対応する。
  • 複数の Web アプリケーション・Web サイトを
    1つの IIS のアプリケーションに纏めることはできない。

複数プロジェクトから1 Web アプリ・サイトを構成する方法

1つの Web アプリケーション・Web サイトを複数プロジェクトにまとめる方法

裏ワザ的な方法だと思いますが・・・、

補足(最新化): ASP.NET Core では
Razor クラス ライブラリ (RCL) により、
View やページ、静的ファイルを別プロジェクトに置いて合成できる。
原文が「裏ワザ的」としていた構成が、標準機能になった。

WebApp.csproj      … ホスト
  └ 参照 Feature.A.csproj(RCL)… Views / wwwroot を含む
  └ 参照 Feature.B.csproj(RCL)

Web アプリ・サイト間で SessionCookie、Cookie 認証 Ticket を共有する方法(ASP.NET)

上記のようにサイトを纏めなくても、SessionCookie、Cookie 認証 Ticket が共有できれば。

配置

  • Web サイトを本番環境に配置する方法には、

    • ファイル・フォルダのコピー
    • プリコンパイル後のファイル・フォルダのコピー
    • セットアップ プログラムによるインストール

    などがある。

  • Web アプリケーションを本番環境に配置する方法には、

    • 発行、Web Deploy
    • セットアップ プログラムによるインストール

    などがある。

ファイル・フォルダのコピー

  • アセンブリが生成されていない状態でアプリケーションを配布した際の
    初期要求時に JIT コンパイルが実行される。
  • JIT コンパイルによりアセンブリが生成され、その後にアプリケーションが実行される。
  • JIT コンパイルにより生成されたアセンブリは、
    %windir%\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files で確認できる。

プリコンパイル後のファイル・フォルダのコピー

  • 事前コンパイルによりアセンブリを生成しておくことで
    初期要求時の JIT コンパイルを不要にできる。
  • この場合、Web サイトのファイル システム上にアセンブリが生成される。
  • プリコンパイルにより生成されたアセンブリは、
    生成された Web サイトのフォルダの直下にある「bin」フォルダで確認できる。

補足(Web サイトと Web アプリケーションの違い): この節が
2 つを分けて説明しているのは、プロジェクトの種類が違うためである。

Web サイト Web アプリケーション
プロジェクト ファイル 無い(フォルダがそのままプロジェクト) ある(.csproj)
コンパイル 実行時(初回要求時に JIT) ビルド時(1 つの DLL に)
配置 ソース(.aspx.cs)ごとコピー bin の DLL + .aspx

Web サイト形式はソース コードが本番に置かれるため、
セキュリティ・性能の両面で現在は使われない。
詳細は ASP.NETの構成(Webサイト・Webアプリ)を参照。

セットアップ プログラムによるインストール

Web セットアップ プログラムによる Web サイトのインストールが可能。

ASP.NET の配置(発行)


Tags: 移行, .NET開発

NetDevInfraWiki

マイクロソフト系技術情報 Wiki
Open 棟梁 Wiki

(未着手)

開発基盤部会 Wiki

移行管理: DONE / TODO

Clone this wiki locally