説明
サンプル シナリオとして、プロジェクト X、アセンブリ A、およびアセンブリ B があるとします。アセンブリ A はアセンブリ B を参照するため、プロジェクト X には A と B の両方への参照が含まれます。また、プロジェクト X には、アセンブリ A を参照するコードが含まれます (たとえば、A. SomeFunction())。ここで、プロジェクト X を参照する新しいプロジェクト Y を作成します。
したがって、依存チェーンは次のようになります: Y => X => A => B
Visual Studio / MSBuild は賢く、プロジェクト X に必要であると検出された参照のみをプロジェクト Y に持ち込もうとします。これは、プロジェクト Y での参照汚染を回避するために行われます。問題は、プロジェクト X にはアセンブリ B を明示的に使用するコード (B.SomeFunction() など) が実際には含まれていないため、VS/MSBuild は B が必要であることを検出しないことです。したがって、プロジェクト Y の bin ディレクトリにコピーしません。X および A アセンブリのみをコピーします。
解決
この問題を解決するには 2 つの方法があります。どちらの方法でも、アセンブリ B がプロジェクト Y の bin ディレクトリにコピーされます。
- プロジェクト Y のアセンブリ B への参照を追加します。
- アセンブリ B を使用するプロジェクト X のファイルにダミー コードを追加します。
個人的には、いくつかの理由からオプション 2 を好みます。
- 将来、プロジェクト X を参照する別のプロジェクトを追加する場合、アセンブリ B への参照も含めることを忘れないでください (オプション 1 で行う必要があるように)。
- ダミーコードが必要な理由を明示的にコメントして、それを削除しないようにすることができます。そのため、誰かが誤ってコードを削除してしまった場合 (未使用のコードを探すリファクタリング ツールなどで)、ソース管理からそのコードが必要であることを簡単に確認して、それを復元することができます。オプション 1 を使用し、誰かがリファクタリング ツールを使用して未使用の参照をクリーンアップした場合、コメントはありません。参照が .csproj ファイルから削除されたことがわかります。
これは、この状況に遭遇したときに通常追加する「ダミー コード」のサンプルです。
// DO NOT DELETE THIS CODE UNLESS WE NO LONGER REQUIRE ASSEMBLY A!!!
private void DummyFunctionToMakeSureReferencesGetCopiedProperly_DO_NOT_DELETE_THIS_CODE()
{
// Assembly A is used by this file, and that assembly depends on assembly B,
// but this project does not have any code that explicitly references assembly B. Therefore, when another project references
// this project, this project's assembly and the assembly A get copied to the project's bin directory, but not
// assembly B. So in order to get the required assembly B copied over, we add some dummy code here (that never
// gets called) that references assembly B; this will flag VS/MSBuild to copy the required assembly B over as well.
var dummyType = typeof(B.SomeClass);
Console.WriteLine(dummyType.FullName);
}