Side-by-Side Execution と Zero Impact Deployment

どちらも .NET Framework 開発者ガイドに記載されている事柄で、どちらも従来の DLL Hell と呼ばれる問題を解消するための仕組みである。

Side-by-Side Execution (SxS 実行)

SxS とよばれる技術そのものは .NET に限定された技術ではないが、.NET では厳密名 (StrongName) とグローバルアセンブリキャッシュ (GAC) によって広く提供され、その有効性を簡単に享受できる機能である。
開発者ガイドにもあるように、厳密名を持たないアセンブリを SxS 実行することは不可能ではないが、その仕組みを .NET Framework は提供しないし、SxS 実行において部分限定名によるアセンブリ参照は最も避けなければならないことである、とまで記載されているので素直に従うのが身のためであろう。
多くの場所で「バージョンの異なる2つのアセンブリを同時に読み込んで動作する」と解説されているが、もう少し違う言い方をすると「バージョンの異なる2つのアセンブリを明確に区別することができるようにするルール」と「名前の違いを意識せずに利用できる仕組み」いうことができるかな? 前者の名前付けルールとして厳密名があり、後者の仕組みとしてバージョンを意識したコードストーレジとして GAC が用意されている。

Zero Impact Deployment (XCOPY 配布)

SxS 実行そのものは、上に書いたように .NET Framework としてはコードストーレジとして GAC が利用される場合にのみ限定された機能である。しかし、実行環境に配置(インストール)されるすべてのアセンブリが GAC に登録されて管理されるようなことは推奨されておらず、個々のアプリケーションは極力 GAC を利用しないことが推奨されている。
どこぞの本には、「あなたがコンポーネントを作成しており、それを GAC にインストールする前に、世界中の Windows のうち何%にそのコンポーネントがインストールされることを想定しているだろうか?」みたいな設問があり、(記憶の限りでは)70%を下回るようなら GAC にはインストールするな、90%だとしても、本当に GAC にインストールしなければならないか再考せよ。みたいなことがかいてあったような…。
このような GAC の特性における対応として、.NET では SxS 実行ではなく Zero Impact Deployment と呼ばれるアプリケーション配置方法が採用されている。この機能はローカルコピーとアセンブリプローブによって提供されており、従来の DOS/Win32 にあった「環境変数 PATH」との決別でもある。
Zero Impact Deployment では、アプリケーションが利用するアセンブリは、すべてそのアプリケーションの実行イメージのインストール先となるフォルダか、その下位フォルダ*1にローカルコピーとして複製が配置されることになっている。その上で、アセンブリの参照を解決するプローブがアプリケーションの実行イメージの配置されたフォルダより上を検索せず、複数のアプリケーションが使用する異なるバージョンの共通アセンブリを、お互いに影響が発生しないように配置する結果になる。
Zero Impact Deployment で配置されるファイル(ローカルコピーされたアセンブリ)は、.NET Framework の SxS 実行の機能が利用できないので、何らかの方法でアセンブリを独自にバージョン管理しなければならない。インストール先にすべてのアセンブリをローカルコピーしてしまうと、ほとんどのファイルシステムは SxS 実行のために必要なバージョンセンシティブコードストーレジとしての役割を果たせない。


Visual Studio .NET ではプロジェクトに参照設定を行ったあと、作成した参照のプロパティにあるローカルコピー属性を変更することで、ローカルコピーを作成する(SxS 実行を行わなず、Zero Impact Deployment を選択する)か作成しないかを指定することができ、その初期値は GAC に格納されたアセンブリはデフォルトでローカルコピーしない(SxS 実行する)となっている。
なお、Zero Impact Deployment は、.NET 1.0 の頃は SxS Deployment とも呼ばれていたらしく、古い書籍では「サイドバイサイド実行」と「サイドバイサイド配置」などと記述しているものがいくつか発見できる。

*1:この下位フォルダの名称も標準的なものがいくつか決まっている