.NETでのアセンブリのバージョン管理は、現在、アセンブリのバージョンを指定する方法が少なくとも3つあることから、混乱を招く可能性があります。
次に、バージョンに関連する3つの主要なアセンブリ属性を示します。
// Assembly mscorlib, Version 2.0.0.0
[assembly: AssemblyFileVersion("2.0.50727.3521")]
[assembly: AssemblyInformationalVersion("2.0.50727.3521")]
[assembly: AssemblyVersion("2.0.0.0")]
慣例により、バージョンの4つの部分は、メジャーバージョン、マイナーバージョン、ビルド、リビジョンと呼ばれます。
AssemblyFileVersion
一意のビルドを識別することを意図している個々のアセンブリ
通常は、メジャーとマイナーのAssemblyFileVersionを手動で設定してアセンブリのバージョンを反映させ、ビルドシステムがアセンブリをコンパイルするたびにビルドまたはリビジョン、あるいはその両方をインクリメントします。AssemblyFileVersionを使用すると、アセンブリのビルドを一意に識別できるため、アセンブリを問題のデバッグの開始点として使用できます。
現在のプロジェクトでは、ビルドサーバーに、ソース管理リポジトリのチェンジリスト番号をAssemblyFileVersionのビルドとリビジョンの部分にエンコードしています。これにより、ビルドサーバーによって生成されたアセンブリについて、アセンブリからソースコードに直接マッピングできます(ソース管理でラベルやブランチを使用したり、リリースされたバージョンのレコードを手動で保持したりする必要はありません)。
このバージョン番号はWin32バージョンリソースに格納され、アセンブリのWindowsエクスプローラーのプロパティページを表示すると確認できます。
CLRは、AssemblyFileVersionを考慮したり、調べたりしません。
AssemblyInformationalVersion
お使いの製品全体のバージョンを表すことが意図されています
AssemblyInformationalVersionは、製品全体の一貫したバージョン管理を可能にすることを目的としています。これは、おそらく異なるバージョン管理ポリシーで個別にバージョン管理され、異なるチームによって開発される可能性のある多くのアセンブリで構成される場合があります。
「たとえば、製品のバージョン2.0には複数のアセンブリが含まれる場合があります。これらのアセンブリの1つは、同じ製品のバージョン1.0で出荷されなかった新しいアセンブリであるため、バージョン1.0としてマークされています。通常、このバージョン番号のメジャー部分とマイナー部分は、製品のパブリックバージョンを表すように設定します。その後、すべてのアセンブリを含む完全な製品をパッケージ化するたびに、ビルドパーツとリビジョンパーツをインクリメントします。」— Jeffrey Richter、[C#を介したCLR(第2版)] p。57
CLRは、AssemblyInformationalVersionを考慮したり、調べたりしません。
AssemblyVersion
CLRの苦労唯一のバージョンである(しかし、それは全体を気AssemblyVersion
)
AssemblyVersionは、厳密に名前が付けられたアセンブリにバインドするためにCLRによって使用されます。これは、ビルドされたアセンブリのAssemblyDefマニフェストメタデータテーブルと、それを参照するアセンブリのAssemblyRefテーブルに格納されます。
これは非常に重要です。厳密に名前が付けられたアセンブリを参照すると、そのアセンブリの特定のAssemblyVersionに緊密にバインドされるからです。バインディングが成功するには、AssemblyVersion全体が完全に一致する必要があります。たとえば、ビルド時に厳密に名前が付けられたアセンブリのバージョン1.0.0.0を参照するが、実行時にそのアセンブリのバージョン1.0.0.1しか使用できない場合、バインディングは失敗します。(その後、アセンブリバインディングリダイレクトを使用してこれを回避する必要があります。)
全体AssemblyVersion
が一致する必要があるかどうかについての混乱。(はい、そうです。)
アセンブリを読み込むために、AssemblyVersion全体を完全に一致させる必要があるかどうかについては、少し混乱があります。バインディングが成功するためには、AssemblyVersionのMajorとMinorの部分だけが一致すればよいという誤った信念の下にいる人もいます。これは賢明な仮定ですが、最終的には正しくありません(.NET 3.5以降)。CLRのバージョンでこれを確認するのは簡単です。このサンプルコードを実行してください。
私のマシンでは2番目のアセンブリロードが失敗し、フュージョンログの最後の2行で理由が完全に明らかになっています。
.NET Framework Version: 2.0.50727.3521
---
Attempting to load assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f
Successfully loaded assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f
---
Attempting to load assembly: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
Assembly binding for failed:
System.IO.FileLoadException: Could not load file or assembly 'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral,
PublicKeyToken=0b3305902db7183f' or one of its dependencies. The located assembly's manifest definition
does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f'
=== Pre-bind state information ===
LOG: User = Phoenix\Dani
LOG: DisplayName = Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
(Fully-specified)
LOG: Appbase = [...]
LOG: Initial PrivatePath = NULL
Calling assembly : AssemblyBinding, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v2.0.50727\config\machine.config.
LOG: Post-policy reference: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
LOG: Attempting download of new URL [...].
WRN: Comparing the assembly name resulted in the mismatch: Revision Number
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.
この混乱の原因はおそらく、Microsoftがメジャーバージョンとマイナーバージョンのパーツのみを照合することにより、完全なAssemblyVersionのこの厳密な照合について、もう少し寛容にすることを意図していたためだと思います。
「アセンブリを読み込むとき、CLRは要求されているアセンブリのメジャー/マイナーバージョンと一致する最新のインストール済みサービスバージョンを自動的に見つけます。」— Jeffrey Richter、[C#を介したCLR(第2版)] p。56
これは1.0 CLRのベータ1での動作でしたが、この機能は1.0リリースの前に削除されており、.NET 2.0では再表示できませんでした。
「注:ここでは、バージョン番号の考え方について説明しました。残念ながら、CLRはバージョン番号をこのように扱いません。[.NET 2.0]では、CLRはバージョン番号を不透明な値として扱い、アセンブリが別のアセンブリのバージョン1.2.3.4に依存している場合、CLRはバージョン1.2.3.4のみをロードしようとします(バインディングリダイレクトが設定されている場合を除く)。 )。ただし、
Microsoftは、CLRのローダーを将来のバージョンで変更して、アセンブリの特定のメジャー/マイナーバージョンの最新のビルド/リビジョンをロードする予定です。。たとえば、CLRの将来のバージョンでは、ローダーがアセンブリのバージョン1.2.3.4を見つけようとしていて、バージョン1.2.5.0が存在する場合、ローダーは最新のサービスバージョンを自動的に取得します。これは、CLRのローダーに対する非常に歓迎すべき変更です。私は待つことができません。」— Jeffrey Richter、[C#を介したCLR(第2版)] p。164(エンファシス鉱山)
この変更はまだ実装されていないので、Microsoftがこの意図を後回しにしていたと考えるのは安全だと思います。これを変更するのは遅すぎるかもしれません。私はこれらの計画で何が起こったのかを知るためにウェブを検索しようとしましたが、答えは見つかりませんでした。私はまだそれの底に行きたかったです。
それで、私はジェフ・リヒターに電子メールを送り、彼に直接尋ねました—私は誰かが何が起こったか知っているなら、それは彼であると考えました。
彼は12時間以内に土曜日の朝に返答し、.NET 1.0 Beta 1ローダーがアセンブリの最新のビルドとリビジョンを取得するこの「自動ロールフォワード」メカニズムを実装していることを明確にしましたが、この動作は.NET 1.0が出荷される前に復帰しました。後でこれを復活させることを意図していたが、CLR 2.0が出荷される前には実現しなかった。その後、CLRチームを優先するSilverlightが登場したため、この機能はさらに遅れました。それまでの間、CLR 1.0 Beta 1の頃にいたほとんどの人はその後に進んでいるので、すでにすべての困難な作業が行われているにもかかわらず、これが日の目を見る可能性はほとんどありません。
現在の行動は、ここにとどまっているようです。
また、Jeffとの話し合いから、AssemblyFileVersionが追加されたのは「自動ロールフォワード」メカニズムが削除された後であることにも注意してください。1.0Beta 1以降、AssemblyVersionへの変更は顧客にとって重大な変更でした。ビルド番号を安全に保管する場所はありません。AssemblyFileVersionはCLRによって自動的に検査されることはないため、安全な避難所です。おそらく、AssemblyVersionのメジャー/マイナー(互換性のない)部分とビルド/リビジョン(互換性のない)部分を区別しようとするのではなく、2つの異なるバージョン番号を別々の意味で持つことで、より明確になるでしょう。
一番下の行:あなたがあなたの AssemblyVersion
道徳は、他の開発者が参照する予定のアセンブリを出荷する場合、それらのアセンブリのAssemblyVersionを変更するとき(および変更しないとき)には、非常に注意する必要があるということです。AssemblyVersionへの変更は、アプリケーション開発者が新しいバージョンに対して再コンパイルする(これらのAssemblyRefエントリを更新する)か、アセンブリバインディングリダイレクトを使用してバインディングを手動で上書きする必要があることを意味します。
- 下位互換性を目的としたサービスリリースのAssemblyVersionを変更しないでください。
- 重大な変更があることがわかっているリリースのAssemblyVersionを変更してください。
mscorlibのバージョン属性をもう一度見てください。
// Assembly mscorlib, Version 2.0.0.0
[assembly: AssemblyFileVersion("2.0.50727.3521")]
[assembly: AssemblyInformationalVersion("2.0.50727.3521")]
[assembly: AssemblyVersion("2.0.0.0")]
興味深いサービス情報をすべて含んでいるのはAssemblyFileVersionであることに注意してください(このバージョンのリビジョン部分であり、どのService Packを使用しているかがわかります)、一方、AssemblyVersionは退屈な古い2.0.0.0で修正されています。AssemblyVersionに変更を加えると、mscorlib.dllを参照するすべての.NETアプリケーションが新しいバージョンに対して再コンパイルされます。