ASP 1.1 の分離コードにおける参照

ASP.NET フレームワークにおいてコードビハイドは必須ではないし、Visual Studio .NET も必須ではないし、.aspx ファイルやそれに関連付けられた分離コードファイルがどのように扱われるか、@ITこれなんですが、そういった ASP.NET のバックグラウンドの動きをきちんと理解しているかどうか、というのが大きなポイントになる話題ですね。

私は ASP.NET はよくわかってないので、続きを読まれる前にことわっておくと、以降の文章に回答はありません。
投稿題ではコードビハインドとされていますが、ASP.NET の分離コードはコードビハインドとは呼ばない場合が多いようです。さらっと見直す限りではコレといった名称も見つかりませんでしたので、どう呼ぶべきか困ったものではあります。
ASP.NET における .aspx ファイルによるコンテンツページの作成においては、コンテンツページは Page クラス(またはその派生クラス)の派生クラス として生成されます。派生元となる親クラスは @Page ディレクティブの Inherited 属性を利用して指定でき、ソースコードは .aspx ファイルにデザインと共に埋め込むことなります。
分離コード機能は .aspx ファイル以外のファイルへコードを書き分ける機能で、リリース間近の ASP.NET 2.0 ではまさにそのような機能になるのですが、ASP.NET 1.1 では .aspx から自動生成されるソースコードと、分離された分離コードファイルは個別の異なるクラスへとコンパイルされます。これは ASP.NET 1.1 では Inherited 属性と組み合わせることで派生クラスとして生成することで分離コードファイルへと分離したコードを .aspx への取り込みを実現しているということです。
これは非常に単純な仕組みで、とりあえず Page クラスの派生クラスを作成しアセンブリとして完成させれば、あとは @Page ディレクティブの Inherited 属性にクラス名を設定するだけという簡単な手順で利用することができます。

.aspx ファイルの中身を書き換えると、ASP.NETフレームワークは新しい内容に従ったアセンブリを自動生成しますが、Inherited 属性だけで指定された分離コードは分離コードファイルの変更を行っても自動生成されることはありません。分離コードファイルの再構築を行うためには Codebehide 属性か Src 属性を追加する必要があり、特に前者はコードビハイドまたはプロジェクトモードと呼ぶことがあります。
Visual Studio .NET などの開発環境では基本的にプロジェクトモードを利用します。*1 このモードの特徴はアプリケーション内の複数の分離コードファイルが1つのアセンブリコンパイルされることです。逆に、Src 属性を利用したファイルモードでは、1つの分離ファイルに対して1つのアセンブリが生成されるようになっています。*2

前置きが長くなりましたが、ここで Codebehide と Src の違いによる @IT の投稿にあるような問題が発生します。

Src 属性では各分離コードファイルは個別のアセンブリコンパイルされます。個別のアセンブリコンパイルされるということは、参照関係が完全に解決していなければなりません。投稿にあるような構成の場合、Global.asax.cs は Global.dll へコンパイルされ、Global.asax は Global.dll を静的に参照した ASP.Global.dll へコンパイルされ、test1.aspx.vb は test1.dll にコンパイルされて test1.aspx は test1.dll を静的参照した ASP.test1.dll へとコンパイルされます。*3
ここで test.aspx.vbコンパイルするためには、Global.dll への参照設定が必要になりますが、ソースコードの中で参照設定を行うようなディレクティブは現行の C#/VB の上では存在しないため、なんとかして別の手段で設定しなければなりません。
.aspx ファイルでは @Assembly ディレクティブを利用すると、.aspx ファイルから生成されたコードをコンパイルする際の参照設定を追加することができ、この設定は Src 属性で設定した分離コードファイルにも適用されます。つまり、xxx.aspx ファイルにおいて

<%@ Page Src="xxx.cs" %>
<%@ Assembly Name="System.Windows.Forms" %>

などとすることで、xxx.aspx から生成されるコードと xxx.cs の両方のコンパイルに /r:System.Windows.Forms.dll が追加されます。しかし、Global クラスは Global.cs と Global.asax ファイルに記載された動的にコンパイルされるクラスなので、まだアセンブリはありませんし、コンパイル後のアセンブリの名前もわからないため、@Assembly ディレクティブの Name 属性を記述することはできません。*4
@Assembly ディレクティブでは、Name 属性のかわりに Src 属性を利用することもできますが、これもまた曲者です。test1.aspx から @Assembly ディレクティブを利用して Global.asax を参照すると、Global.dll ではなく ASP.Global.dll を参照設定することになります。通常はこれは問題なく働くのかもしれませんが、今回の場合は ASP.Global.dll に保存されている Global 派生クラスではなく、Global クラスそのものの参照情報が必要なため、コンパイルエラーになってしまいます。もちろん、static な要素も継承されるので、ASP.Global.dll 内の派生クラスにも目的のプロパティやメソッドは存在しますが、その派生クラスの名前が不明な状況ではソースコードをうまく記述することができません。

こういうときは @Reference が使えるんでしょうかね? @Application と @Reference ってろくな説明がみあたらないのだけど…。

*1:Visual Studio .NET 2003 ではプロジェクトモードのみがデザイナによって設計可能です。

*2:これは Microsoft の実装の話であり、ASP.NET 互換の別の実装上で保障されるわけではない

*3:実際に生成されるアセンブリのファイル名はランダムです

*4:コンパイルオプションを自由に記述できる CompilerOptions 属性も同様の理由で利用できないでしょう