ホーム > ASP.NET, プログラミング, Visual Basic > ASPXファイルやjavascriptファイル、スタイルシートファイルもリンク参照したい。

ASPXファイルやjavascriptファイル、スタイルシートファイルもリンク参照したい。


Visual Studioを使ったアプリケーション開発では、他のプロジェクトのクラスやリソースを利用したい場合は、アセンブリの参照を行ってクラスやリソースを共有します。しかしアセンブリの参照では、WPFとSilverlightのようにアセンブリの互換性がなかったり、テキストファイルなどを直接参照することはできません。

リンク参照とコンテンツファイル

複数のプロジェクトでファイルそのものを共有したい場合に利用するのが、リンク参照です。例えばWPFとSilverlightではアセンブリレベルの互換性は一部のアセンブリだけですが、ソースをリンク参照することで同じソースコードを利用してコンパイルすることができます。

複数のプロジェクトでファイルを共有するには?

この機能を使うと、ソースコードであれば問題なくビルドすることはできのですが、ファイルそのものを実行時に利用するようなHTMLや画像ファイルの場合は困ります。あくまでリンクがVisual Studioのビルド時に解決されるだけなので、実際のコンテンツファイルは参照先にしか存在しないので、ブラウザーなどでそのURLを見てもファイルが存在しないのです。

image image

プロジェクト上はCommonPageプロジェクトのASPXがリンク参照されているが、ブラウザーでそのASPXを参照すると、ファイルが存在しないエラーになってしまう。

リンクの解決とファイルのコピー

じゃぁビルド時にプロジェクトファイルの内容を見て、リンク先のファイルを自分のフォルダーにコピーしてあげればいいじゃん!!って事で、まずはプロジェクトファイルを確認してみましょう。プロジェクトファイルをテキストエディターなどでひらくと、リンク参照先は/Project/ItemGroup/Content/Linkに定義されいることが確認できます。

  <ItemGroup>
    <Content Include="..\CommonPages\pages\共通ページ.aspx">
      <Link>pages\共通ページ.aspx</Link>
    </Content>
    <Content Include="Default.aspx" />
    <Content Include="pages\個別ページ.aspx" />
    <Content Include="Web.config" />
    <Content Include="Web.Debug.config">
      <DependentUpon>Web.config</DependentUpon>
    </Content>
    <Content Include="Web.Release.config">
      <DependentUpon>Web.config</DependentUpon>
    </Content>
  </ItemGroup>

ここまでわかればLINQ to XMLでざっくりと取れるわけですが、どうせなら、VB.NETでXML Schemaをつくって、インテリセンス経由でリンク参照の一覧を取り出してみましょう。まずは、アイテムの新規追加から、Xml To Schemaを選択します。

新しい項目の追加 - ConsoleApplication1

次に表示さる、XMLドキュメントからのXMLスキーマセットの生成では、ファイルから追加ボタンをクリックして、リンク参照を含んだVBやC#のプロジェクトファイルを追加します。

XML ドキュメントからの XML スキーマ セットの生成

あとは、こんなふうにコードを記述すると、リンクとして追加したファイルの参照先の一覧を取得することができます。

Imports <xmlns:ns="http://schemas.microsoft.com/developer/msbuild/2003">

    ''' <summary>
    ''' リンクされているプロジェクトアイテムを取得します。
    ''' </summary>
    Private Shared Function GetLinkItems(ByVal projectFilePath As String) As Dictionary(Of String, String)
        Dim xml = XElement.Load(projectFilePath)
        Dim query = From element In xml...<ns:ItemGroup>.<ns:Content> _
                   Where element.<ns:Link> IsNot Nothing AndAlso _
                         Not String.IsNullOrEmpty(element.<ns:Link>.Value) _
                   Order By element.@Include

        Dim linkItems As New Dictionary(Of String, String)
        For Each item In query
            Console.WriteLine(String.Format("追加 {0}", item.@Include))
            linkItems.Add(item.@Include, item.<ns:Link>.Value)
        Next
        Return linkItems
    End Function

あとは、取得したファイルの一覧をループして、プロジェクトディレクトリーの相対パスにファイルをコピーしていくだけです。

        Dim linkItems = GetLinkItems(targetProjectPath)
        Dim projectDirectoryPath = Path.GetDirectoryName(targetProjectPath)
        Console.WriteLine("ファイルのコピーを開始します。")
        For Each linkItem In linkItems
            Dim copyFrom = Path.Combine(projectDirectoryPath, linkItem.Key)
            Dim copyTo = Path.Combine(projectDirectoryPath, linkItem.Value)

            Copy(copyFrom, copyTo)
        Next

ここで気をつけたいこととして、ソース管理ツールを使っている場合、ディレクトリーの中がからの場合はディレクトリーそのものが作られないことがあります。Visual Studioのリンクとして参照を利用すると物理ファイルが存在しないので、コピー先のフォルダーが存在しないことがあるので、コピーするときは必ずフォルダーの存在有無を確認して、フォルダーが存在しなかったら作成してあげる必要があります。

    ''' <summary>
    ''' ファイルのコピー(上書き)
    ''' </summary>
    Private Shared Sub Copy(ByVal CopyFrom As String, ByVal CopyTo As String)
        Dim dir = Path.GetDirectoryName(CopyTo)
        If Not Directory.Exists(dir) Then
            Directory.CreateDirectory(dir)
        End If

        Console.WriteLine(String.Format("[Copy]:{0}→{1}", CopyFrom, CopyTo))
        File.Copy(CopyFrom, CopyTo, True)
    End Sub

あとはこれを正常時は0を、異常時には1を返すコンソールアプリケーションにしてにしてあげれば、Visual Studioのビルド後動作に組み込むことができます。

ビルド後動作の追加

ビルド後の動作を設定したい場合、VBのプロジェクトであれば、プロジェクトのプロパティー⇒[コンパイル]⇒[ビルドイベント]から、C#であれば、プロジェクトのプロパティー⇒[ビルドイベント]から設定できます。

今回はWebプロジェクトのプロジェクトがビルドされた後に共通Webプロジェクトからファイルをコピーしたいので、ビルド後に実行するコマンドラインに次のようなコマンドを記述します。

 

“$(ProjectDir)..\Tools\ConsoleApplication1.exe” “$(ProjectPath)”

 

$()で記述されているのはVisual StudioというかMsBuildのマクロの一種です。ここではプロジェクトフォルダーの一つ上のToolsフォルダに作ったコピー用のコンソールアプリケーションを呼び出し、引数にプロジェクトファイルのパスを与えています。

ビルドを実行すると、出力ウインドウには次のようにログが出力されます。実際にエクスプローラーなどで確認してみると、リンクとして参照したファイルがコピーされているのを確認できます。

—— ビルド開始: プロジェクト: Page2, 構成: Debug Any CPU ——

Page2 -> C:\Source\LinkSample\Page2\bin\Page2.dll

追加 ..\CommonPages\pages\共通ページ.aspx

ファイルのコピーを開始します。

[Copy]:c:\Source\linksample\page2\..\CommonPages\pages\共通ページ.aspx→c:\Source\linksample\page2\pages\共通ページ.aspx

ファイルのコピーが終了しました。

image

動作確認

実際にWebブラウザーで確認すると、ちゃんと表示されるのを確認できます。

image

注意)ソリューションエクスプローラーなどでブラウザーで確認を行った場合、~/参照先の「Webサイト/参照したファイルのパス」が表示されてしまいうまく参照できませんが、Webブラウザーでちゃんとしたパスを指定すれば確認できます。

注意)あっそうだ、リンク参照とは別にCommonPageプロジェクトに対する参照も追加するのを忘れないようにしておいてくださいね。今回はCSファイルやVBファイルはコピーしていないので、コードファイルは参照先のものを使っていますから。CSファイルやVBファイルをコピーしたいときはコンソールアプリケーション側に手を入れてちょっと細工をしてあげてください。ダウンロードようのプロジェクトにはコメントとしてコードが入っているので参考にしてください。

今回のプロジェクトはここからダウンロードできます。

http://cid-b17f5fcd8095628b.office.live.com/self.aspx/%E5%85%AC%E9%96%8B/LinkSample.zip

  1. まだコメントはありません。
  1. 2011年1月7日 12:46 AM

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。