-
Notifications
You must be signed in to change notification settings - Fork 0
MS_VSSolutionStructure
- 戻る(.NET開発)
Visual Studio の、「ソリューション」・「プロジェクト」の構成を検討する際の
ポイントについて説明する。
Visual Studio では、開発するプログラムを、
ソリューション・プロジェクトという単位で管理する。
-
1つのプログラムは、1-複数のアセンブリ(EXE や DLL ファイル)から
構成される場合がある。 -
1つの Web サイト・Web アプリケーションも、
1-複数のアセンブリやコンテンツ ファイルから構成される。 -
また、各アセンブリをコンピュータにインストールするための
「セットアップ プログラム」・「Web セットアップ プログラム」などがある。
補足(3 つの単位の対応関係): 混乱しやすいので先に整理する。
ソリューション(*.sln) … 1 つ以上のプロジェクトを束ねる「作業単位」 └ プロジェクト(*.csproj) … 1 つのアセンブリを作る「ビルド単位」 └ アセンブリ(*.dll) … 1 つの「配置・バージョン管理単位」原則 1 プロジェクト = 1 アセンブリであり、
ソリューションはビルドはするが、成果物そのものではない。
.NETアセンブリ も併せて参照。
-
*.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 での配布)
一般的に小規模開発の場合は分割を少なくして、大規模開発の場合に分割を検討する。
-
管理が容易になる。
-
開発作業の分担が可能になる。
-
部品化等により差し替えが容易になる。
-
修正箇所毎、ビルド範囲を絞る事ができる。
-
プロセス、アプリケーション ドメイン分割により、
障害範囲を少なくできる。
-
管理が煩雑になる。
-
開発作業の分担ができなくなる。
-
部品化等により差し替えができなくなる。
-
修正箇所毎、ビルド範囲を絞る事ができなくなる。
-
プロセス、アプリケーション ドメイン分割により、
プロセス間通信が必要になる。
補足(この表の読み方): メリットとデメリットが
同じ項目の裏返しになっている点が要点である。
原文は「分割しない場合のデメリット」を並べているのではなく、
分割しすぎた場合のデメリットを並べていると読むのが正しい。分割しない ◀──────────────────▶ 分割しすぎ ・ビルドが遅い ・管理が煩雑 ・差し替えできない ・参照関係が追えない ・分担しにくい ・ビルド順序が複雑補足(実務上の目安): 現在の一般的な指針は
**「プロジェクトは少ないほど良い」**である。
- プロジェクト数はビルド時間に直結する(1 プロジェクト = 1 コンパイル)
- アセンブリ境界は実行時のコストでもある(型のロード、JIT)
- 「レイヤごとにプロジェクトを分ける」だけでは設計上の意味が薄い
(フォルダとinternalで足りることが多い)分けるべき明確な理由があるときにだけ分ける、というのが原則。
分ける理由 例 別々に配布する NuGet パッケージにする、他システムへ提供する 参照の向きを強制したい ドメイン層がインフラ層を参照しないことを保証する ターゲットが違う 一方は netstandard2.0、他方はnet8.0テストプロジェクト 本体と一緒に配布しない
-
Web アプリケーション、Web サイト毎に
アプリケーション ドメインは異なる。 -
Web アプリケーション、Web サイト
(アプリケーション ドメイン)を格納するワーカプロセス(プロセス)を選択できる。
補足(最新化): アプリケーション ドメインは
.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 プライベート・リポジトリ)。
- 1つの Web アプリケーション・Web サイトは、
1つの IIS のアプリケーションと対応する。 - 複数の Web アプリケーション・Web サイトを
1つの IIS のアプリケーションに纏めることはできない。
1つの Web アプリケーション・Web サイトを複数プロジェクトにまとめる方法
裏ワザ的な方法だと思いますが・・・、
- マイクロソフト サポート オンライン
チーム開発用に複数のプロジェクトから ASP.NET アプリケーションを作成する方法
http://support.microsoft.com/default.aspx?scid=kb;ja;JP307467
補足(最新化): 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 +.aspxWeb サイト形式はソース コードが本番に置かれるため、
セキュリティ・性能の両面で現在は使われない。
詳細は ASP.NETの構成(Webサイト・Webアプリ)を参照。
Web セットアップ プログラムによる Web サイトのインストールが可能。
Tags: 移行, .NET開発
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。