次の方法で共有


第 2 章: "Longhorn" アプリケーションの構築

 

概要
第 1 章: "Longhorn" アプリケーション モデル

第 2 章: "Longhorn" アプリケーションの構築

Brent Rector
ワイズフクロウコンサルティング

2003 年 11 月

内容

Microsoft .NET ビルド エンジン: MSBuild.exe
MSBuild を使用した Hello World のビルド
MSBuild の用語
Longhorn 実行可能アプリケーションのビルド
Longhorn ライブラリ アセンブリの構築
Longhorn ドキュメントの作成
クラス宣言としての XAML ファイル
アプリケーション マニフェスト
配置マニフェスト
アプリケーションの実行
別のビルド システムを作成する理由
概要

Longhorn アプリケーションをビルドするには、Longhorn Software Development Kit (SDK) がインストールされている必要があります。 または、Longhorn をサポートする Microsoft® Visual Studio® リリースをインストールすることもできます。 この書籍では、ウィザード、ファンシー コード生成機能、およびプロジェクトビルド機能によって、実際に何が起こるかを隠しているため、Visual Studio の使用については説明しません。 私はあなたがツールに頼る前に、ツールが何をするのかを理解する必要があると信じています。

Longhorn SDK をインストールすると、Longhorn アプリケーションをビルドできるコマンド プロンプト セッションの作成に使用できる一連のスタート メニュー項目が作成されます。 Microsoft Windows® XP 32 ビット システムでアプリケーションのデバッグ バージョンをビルドするには、次のメニュー項目を移動して、適切なコマンド プロンプト セッションを作成します。

  • 始める
  • プログラム
  • Microsoft Longhorn SDK
  • [ビルド環境] ウィンドウを開く
  • Windows XP 32 ビット ビルド環境
  • Windows XP 32 ビット ビルド環境の設定 (デバッグ)

Microsoft .NET ビルド エンジン: MSBuild.exe

MSBuild は、Longhorn アプリケーションの構築に使用する主要なツールです。 ヘルプ コマンド ライン オプションを使用して MSBuild を実行すると、その使用状況に関する詳細情報を取得できます。

MSBuild /?

次に示すように、コマンド ライン引数を指定せずに MSBuild を実行すると、現在の作業ディレクトリで、"proj" で終わるファイル名 (.proj、.csproj など) が検索されます。見つかると、そのファイル内のディレクティブに従ってプロジェクトがビルドされます。

MSBuild

ディレクトリに複数のプロジェクト ファイルがある場合は、コマンド ラインで適切なプロジェクト ファイルを指定できます。

MSBuild <ProjectName>.proj

通常、MSBuild はプロジェクト ファイルに既定のターゲットをビルドします。 これをオーバーライドし、ビルドするターゲットを指定できます。 たとえば、CleanBuildという名前 ターゲットをビルドするには、次のように MSBuild を呼び出します。

MSBuild /t:Cleanbuild

MSBuild を使用した Hello World のビルド

簡単なナビゲーションベースの Hello World アプリケーションを作成するために必要なファイルを見てみましょう。 後で、各ファイルの目的と使用方法について詳しく説明します。

まず、Application オブジェクトを定義する必要があります。 これは、通常、アプリケーション定義ファイルと呼ばれるファイルで行います。 この HelloWorldApplication.xaml ファイルは、Application オブジェクトを定義します。

HelloWorldApplication.xaml

<NavigationApplication xmlns="https://schemas.microsoft.com/2003/xaml" 
                       StartupUri="HelloWorld.xaml" />

この定義には、「Application オブジェクトの場合は、MSAvalon.Windows.Navigation.NavigationApplication クラスのインスタンスを使用します。 起動時に、アプリケーションは HelloWorld.xaml ファイルで定義されているユーザー インターフェイス (UI) に移動して表示する必要があります。

HelloWorld.xaml ファイルの内容を次に示します。 これは、第 1 章の前の Hello World の例のもう少し興味深いバージョンです。

HelloWorld.xaml

<Border xmlns="https://schemas.microsoft.com/2003/xaml">
  <FlowPanel>
    <SimpleText Foreground="DarkRed" FontSize="14">Hello World!</SimpleText>   </FlowPanel>
</Border>

単純な Hello World アプリケーションのすべての "コード" が用意されたので、アプリケーションのビルド方法を定義するプロジェクト ファイルが必要です。 HelloWorld.proj ファイルを次に示します。

HelloWorld.proj

<Project DefaultTargets="Build">
  <PropertyGroup>
    <Property Language="C#" />   
    <Property DefaultClrNameSpace="IntroLonghorn" />
    <Property TargetName="HelloWorld" />
  </PropertyGroup>

  <!--Imports the target which contains all the common targets-->
  <Import Project="$(LAPI)\WindowsApplication.target" />

  <ItemGroup>
    <!-- Application markup -->
    <Item Type="ApplicationDefinition" Include="HelloWorldApplication.xaml" />
   
    <!-- Compiled Xaml Files list -->
    <Item Type="Pages" Include="HelloWorld.xaml"/>      
  </ItemGroup>
</Project>

これら 3 つのファイルをディレクトリに配置します。 Longhorn SDK コマンド プロンプトを開き、ファイルを含むディレクトリに移動して、MSBuild を実行します。 プログラムが実行可能ファイルにコンパイルされます。

この章の後半で、アプリケーション定義ファイルの内容を確認します。 第 3 章では、UI の定義に使用できる拡張アプリケーション マークアップ言語 (XAML) 要素の多くについて詳しく説明します。 プロジェクト ファイルを詳しく見る前に、MSBuild の用語をいくつか確認しましょう。

MSBuild の用語

いくつかの MSBuild 要素の定義を確立してみましょう。 プロパティ はキーと値のペアです。 Propertyの値は、環境変数、コマンドライン スイッチ、またはプロジェクト ファイル内の Property 定義から取得できます。次に示します。

<Property OutputDir="bin\" />

項目 は、ファイルの配列と考えることができます。 項目 にはワイルドカードを含めることができます。また、特定のファイルを除外することもできます。 MSBuild では、次に示すように、ItemType 属性を使用して項目を分類します。

<Item Type="Compile" Include="*.cs" Exclude="DebugStuff.cs" />

タスク は、ビルド プロセスのアトミック単位です。 タスク は、Property 要素、Item 要素、またはプレーン文字列から入力パラメーターを受け取ることができます。 タスク は、タスクを実行するために必要なビルド .NET データ型を識別します。 タスク は、他の タスク消費する アイテムを出力できます。 MSBuild には多くのタスクが含まれており、そのすべてが次のように大きく分類できます。

  • .NET ツール のタスク
  • デプロイ タスク
  • シェル タスク

たとえば、C# コンパイラ ビルド ツールとして呼び出、名の を持つタスク Sources 属性で指定されたすべての Item 要素 (型が Compile の item 要素を指定します) をアセンブリにコンパイルします。 を使用して、Item 出力としてアセンブリを生成します。

<Task Name="Csc" AssemblyName="$(OutputDir)\HelloWorld.exe"
                 Sources="@(Compile)" />

ターゲット は、ビルド プロセスの 1 つの論理ステップです。 ターゲット は、タイムスタンプ分析を実行できます。 これは、ターゲット が不要な場合は実行されないことを意味します。 ターゲット は、次に示すように、1 つ以上の タスクを実行して目的の操作を実行します。

<Target Name="CopyToServer"
        Inputs="$(OutputDir)\HelloWorld.exe"
        Outputs="\\DeployServer\$(BuildNum)\HelloWorld.exe"
        DependsOnTargets="Compile">

  <Task Name="Copy" ... />
</Target>

Condition 属性は、ステートメントを する場合の単純な とほぼ同じです。 条件 は、2 つの文字列を比較したり、ファイルまたはディレクトリの存在を確認したりできます。 条件 をプロジェクト ファイル内の任意の要素に適用できます。 たとえば、Configuration プロパティの値が Debug場合にのみ定義されるプロパティのグループを次に示します。

<PropertyGroup Condition=" '$(Configuration)'=='Debug' " >
    <Property ... />
    <Property ... />
</PropertyGroup>

Import は、次の例に示すように、C/C++ #include ステートメントとほぼ同じです。 プロジェクトをインポートすると、インポートされたプロジェクトの内容が論理的にインポート プロジェクトの一部になります。

<Import Project="$(LAPI)\WindowsApplication.target" />

用語が間に合わないので、一般的なプロジェクト ファイルを調べてみましょう。

Longhorn 実行可能アプリケーションのビルド

実行可能な Longhorn アプリケーションをビルドする単純で比較的包括的なプロジェクト ファイルを次に示します。

<Project DefaultTargets="Build">
  <PropertyGroup>
    <Property Language="C#" />
    <Property DefaultClrNameSpace="IntroLonghorn" />
    <Property TargetName="MyApp" />
  </PropertyGroup>

  <Import Project="$(LAPI)\WindowsApplication.target" />

  <ItemGroup>
    <Item Type="ApplicationDefinition" Include="MyApp.xaml" />

    <Item Type="Pages" Include="HomePage.xaml" />
    <Item Type="Pages" Include="DetailPage.xaml" />
    <Item Type="Code" Include="DetailPage.xaml.cs"/>

    <Item Type="DependentProjects" Include="MyDependentAssembly.proj" /> 

    <Item Type="Components" Include="SomeThirdParty.dll" />

    <Item Type="Resources" Include="Picture1.jpg"
          FileStorage="embedded" Localizable="False"/>
    <Item Type="Resources" Include="Picture2.jpg"
          FileStorage="embedded" Localizable="True"/>
  </ItemGroup>
</Project>

Project 要素

すべてのプロジェクト ファイルは、Projectという名前 ルート要素定義で始まります。 その DefaultTargets 属性は、ターゲットを指定しない場合にシステムがビルドするターゲットの名前を指定します。 この例では、既定では、ビルドという名前のターゲットをシステムがビルドする必要があることを指定します。

PropertyGroup および プロパティ 要素

ビルド ルールは、プロパティ値に基づいて条件付きで実行できます。 前述のように、プロパティの値は、環境変数、MSBuild コマンド ライン スイッチ、またはプロジェクト ファイル内のプロパティ定義から取得できます。

アプリケーションのプロジェクトでは、少なくとも 言語の と TargetName プロパティの値 指定する必要があります。 この例では、言語が C# であり、結果のアプリケーションの名前が MyAppされるように指定します。 DefaultClrNameSpaceという名前のプロパティに値 割り当てることもできます。

ビルド システムは、各 XAML ファイルをマネージド クラス定義にコンパイルします。 既定では、マネージド クラスの名前は XAML ソース ファイルの基本ファイル名と同じです。 たとえば、Markup.xaml ファイルは、Markupという名前のクラス 定義にコンパイルされます。 DefaultClrNameSpace プロパティを IntroLonghornに設定することで、生成されたクラス名のプレフィックスを IntroLonghorn 名前空間に付けてもらうことをビルド システムに求めます。 このため、ビルド システムは Markup.xaml 定義 IntroLonghorn.Markup という名前のクラスを生成します。

他のプロジェクトをインポートする前にプロパティを定義したので、インポートされたプロジェクトのルールでは、指定したプロパティ値が使用されます。たとえば、言語 プロパティを C#として定義しているため、C# アプリケーションの適切なビルド規則 取得します。

Import 要素

Build ターゲットのルールによって、Longhorn アプリケーションの実行可能ファイルが生成されます。 すべてのプロジェクト ファイルでこれらのビルド 規則を指定するのは面倒で反復的です。 プロジェクト ファイルの少し後で、次の定義を使用して、WindowsApplication.targetという名前 定義済みのプロジェクト ファイルをインポートします。

  <Import Project="$(LAPI)\WindowsApplication.target" />

このインポートされたファイルには、Windows アプリケーションをビルドするための標準的なビルド規則が含まれており、(間接的に) ビルドという名前 ターゲットを定義します。

ItemGroup および Item 要素

ItemGroup 要素とその子 Item 要素は、アプリケーションのビルドに必要なすべてのパーツを定義します。

次に示すように、ApplicationDefinitionの を持つ 1 つの 項目 必要があります。 この 項目 は、アプリケーションに使用する Application オブジェクトを記述するファイルを指定します。 Application オブジェクトは、通常、MSAvalon.Windows.Application クラスまたは MSAvalon.Windows.Navigation.NavigationApplication クラスのインスタンスです。どちらもこの章の後半で説明します。

<Item Type="ApplicationDefinition" Include="MyApp.xaml" />

次に示すように、Pages を持つ各 項目 は、一連の XAML ファイルを定義します。 ビルド システムは、これらの XAML 定義を、結果のアセンブリに含まれるクラスにコンパイルします。

<Item Type="Pages" Include="HomePage.xaml" />
<Item Type="Pages" Include="DetailPage.xaml" />

Code を持つ各 項目 は、次に示すようにソース ファイルを表します。 ビルド システムは、プロジェクトの Language プロパティによって選択された適切なコンパイラを使用して、これらのソース ファイルをコンパイルします。

<Item Type="Code" Include="DetailPage.xaml.cs"/>

このプロジェクトは、他のプロジェクトに依存する場合があります。 ビルド システムでは、このプロジェクトをビルドする前に、これらの依存プロジェクトをコンパイルする必要があります。 DependentProjects を持つ 項目 を使用して、このような依存プロジェクト 一覧表示します。

<Item Type="DependentProjects" Include="MyDependentAssembly.proj" /> 

このプロジェクトのコードでは、事前構築済みアセンブリ (コンポーネント アセンブリとも呼ばれます) で型を使用できます。 このようなコンポーネント アセンブリを使用してコードをコンパイルするには、コンパイラに各アセンブリへの参照が必要です。 さらに、アプリケーションをデプロイするときは、これらのコンポーネント アセンブリもデプロイする必要があります。 各コンポーネント アセンブリを一覧表示するには、コンポーネントタイプ を持つ Item を使用します。

<Item Type="Components" Include="SomeThirdParty.dll" />

参照されるアセンブリは、コンポーネント アセンブリとは若干異なります。 どちらの場合も、コードは事前構築済みアセンブリの型を使用します。 ただし、参照アセンブリはアプリケーションの一部として出荷しませんが、コンポーネント アセンブリはアプリケーションの一部として出荷します。 ビルド システムはこの区別を認識している必要があります。

参照 を持つ 項目 を指定して、コンパイラがビルド時に指定したアセンブリを参照する必要があることを示しますが、アセンブリはアプリケーションの展開に含まれません。 ビルド システムには、標準システム アセンブリ (mscorlib.dll、System.dll、PresentationFramework.dllなど) への参照が自動的に含まれます。 などです。ただし、アプリケーションで参照する必要がある非標準アセンブリを追加する必要があります。

<Item Type="References" Include="SharedThirdParty.dll" />

アプリケーションでリソースを使用する場合もあります。 Resources を持つ 項目 は、次に示すように、アプリケーションで使用されるリソースについて説明します。 ビルド システムは、結果のアセンブリにリソースを埋め込んだり、スタンドアロン ファイルとして含めたりすることができます。 ビルド システムでは、ローカライズ可能なリソースをサテライト アセンブリに配置することもできます。

<Item Type="Resources" Include="Picture1.jpg"
      FileStorage="embedded" Localizable="False"/>
<Item Type="Resources" Include="Picture2.jpg"
      FileStorage="embedded" Localizable="True"/>

Longhorn ライブラリ アセンブリの構築

また、実行可能アプリケーションに加えてライブラリをビルドすることもできます。 アプリケーション プロジェクトとライブラリ プロジェクトの主な違いは次のとおりです。

  • ライブラリ プロジェクトでは、TargetType プロパティの値を Libraryに設定します。
  • 通常、ライブラリ プロジェクトにはアプリケーション定義項目は含まれません。

ライブラリを作成するプロジェクト ファイルの例を次に示します。

<Project DefaultTargets="Build">
  <PropertyGroup>
    <Property Language="C#" />
    <Property DefaultClrNameSpace="IntroLonghorn" />
    <Property TargetName="MyLibrary" />
    <Property TargetType="Library" />
  </PropertyGroup>

  <Import Project="$(LAPI)\WindowsApplication.target" />

  <ItemGroup>
    <Item Type="Pages" Include="ErrorPage.xaml" />
    <Item Type="Code" Include="ErrorPage.xaml.cs"/>
    <Item Type="Code" Include="Utilities.cs"/>

    <Item Type="DependentProjects" Include="MyDependentAssembly.proj" /> 

    <Item Type="Components" Include="SomeThirdParty.dll" />

    <Item Type="Resources" Include="Picture1.jpg"
          FileStorage="embedded" Localizable="False"/>
    <Item Type="Resources" Include="Picture2.jpg"
          FileStorage="embedded" Localizable="True"/>
  </ItemGroup>
</Project>

Longhorn ドキュメントの作成

XAML を使用してアプリケーションをビルドする方法に限定されるわけではありません。 また、XAML ファイルを使用して、ユーザーが読み取るための高度に対話型のインテリジェントにレンダリングされたアダプティブ ドキュメントを作成することもできます。 この場合、XAML ファイルはドキュメントのページをまとめて表します。 MSBuild エンジンを使用して、このようなドキュメントをビルドできます。

アプリケーションの代わりにドキュメントをビルドするためのプロジェクト ファイルの変更は軽微です。

  • TargetType プロパティの値をドキュメント設定します。
  • 適切なビルド 規則の WindowsDocument.target プロジェクトをインポートします。
  • 他のすべてのプロジェクト ファイルを通常どおり含めます。

DocumentTargetType が実際に生成する内容を理解することが重要です。 ドキュメントをビルドすると、ビルド出力は .container ファイルになり、ビルド システムは速度ではなくダウンロード用にコンテナーの内容を最適化します。 コンテナー ファイルは、Windows 構造化ストレージ (DocFile とも呼ばれます) 形式の拡張子です。 Longhorn コンテナー処理では、部分的にダウンロードされたファイルのレンダリングを可能にする機能が提供されます。 そのため、アプリケーションの実行を開始する前にコンテナー全体をダウンロードする必要はありません。

さらに、MSBuild にコンテナー ファイルの作成を依頼すると、各 XAML ファイルがバイナリ XAML (BAML) と呼ばれる XML のバイナリ表現にコンパイルされます。 BAML は、元のテキスト ファイルまたはコンパイル済みのto-IL アセンブリよりもはるかにコンパクトです。 BAML ファイルのダウンロードは、より迅速に(ダウンロード用に最適化されています)、インタープリターは実行時にそれらを解析して、ファイルに記述されているクラスのインスタンスを作成する必要があります。 したがって、このようなファイルは速度のために最適化されていません。 これまでは、コンパイル済みのto-IL ファイル (CAML ファイルとも呼ばれ、コンパイル済み XAML の略) を生成してきました。

電子ドキュメントを作成するプロジェクト ファイルの例を次に示します。

<Project DefaultTargets="Build">
  <PropertyGroup>
    <Property TargetType="Document" />
      <Property Language="C#" />
      <Property DefaultClrNameSpace="IntroLonghorn" />
      <Property TargetName="MyDocument" />
  </PropertyGroup>
    
  <Import Project="$(LAPI)\WindowsDocument.target" />

  <ItemGroup>
    <Item Type="ApplicationDefinition" Include="MyApp.xaml" />

    <Item Type="Pages" Include="Markup.xaml" />
    <Item Type="Pages" Include="Navigate.xaml" />
    <Item Type="Code" Include="Navigate.xaml.cs"/>

    <Item Type="Resources" Include="Picture1.jpg"
          FileStorage="embedded" Localizable="False"/>
    <Item Type="Resources" Include="Picture2.jpg"
          FileStorage="embedded" Localizable="True"/>
  </ItemGroup>
</Project>

さまざまな種類の Longhorn アプリケーションとコンポーネントをビルドする方法を学習したので、XAML ファイルの詳細を見てみましょう。 具体的には、XAML ファイルを .NET クラスに変換する場合のビルド システムの動作を見てみましょう。

クラス宣言としての XAML ファイル

アプリケーション定義ファイルは、アプリケーションの Application オブジェクトのクラスを定義する XAML ファイルです。 ただし、一般に、XAML ドキュメントは単にクラスを定義するファイルです。 XAML 定義によって生成されるクラスは、XML ドキュメントのルート要素名に関連付けられているクラスから派生します。 既定では、ビルド システムでは、生成されたクラス名として XAML 基本ファイル名が使用されます。

ナビゲーション アプリケーションのアプリケーション定義ファイルの作成

ApplicationDefinitionType を持つ Item 要素には、Application オブジェクトを定義する XAML ファイルの名前が指定されていることを思い出してください。 つまり、この要素は、アプリケーションのエントリ ポイントを含む XAML ファイルを指定します。 Longhorn プラットフォームは、このファイルで定義した MSAvalon.Windows.Application派生型のインスタンスを作成し、アプリケーションの起動、シャットダウン、ナビゲーションを管理できるようにします。

第 1 章では、アプリケーション インスタンスをプログラムで作成して使用する方法について説明しました。 次の XAML ファイルでは、マークアップを使用して、プロジェクトの Application オブジェクトを定義します。

<NavigationApplication xmlns="https://schemas.microsoft.com/2003/xaml" 
                       StartupUri="HelloWorld.xaml" />

ほとんどのLonghornアプリケーションはナビゲーションベースのアプリケーションであり、多くの場合、標準の NavigationApplication オブジェクトを再利用します。 このアプリケーション定義ファイルは、StartupUri 属性の値のみを変更することで、ほとんどのナビゲーション ベースのアプリケーションに再利用できます。

たとえば、前のアプリケーション定義が HelloWorldApplication.xaml ファイルに存在し、前に示した HelloWorld.proj プロジェクト ファイルを使用している場合、ビルド システムは次のクラス宣言を生成します。

namespace IntroLonghorn {
  class HelloWorldApplication :
           MSAvalon.Windows.Navigation.NavigationApplication {
.
.
.
   }
 }

名前空間は、プロジェクト ファイル内の DefaultClrNameSpace 宣言から得られ、宣言されたクラス名は基本ファイル名と同じになり、宣言されたクラスは XAML ファイル内のルート要素によって表されるクラスを拡張します。

属性を使用した生成されたコードのカスタマイズ

XAML ファイルでルート要素を宣言する場合は、ルート要素の属性を使用して、生成されたクラス宣言の名前を制御できます。 次の省略可能な属性のいずれかを使用できます。

  • プレフィックスを定義という名前の名前空間 関連付ける名前空間プレフィックス定義。 言語の とクラスの 属性を使用するには、この名前空間のプレフィックス 定義する必要があります。 従来、def プレフィックスが使用されていました。
  • XAML ファイル内の任意のインライン コードで使用されるプログラミング言語を指定する 言語 属性 (定義 名前空間で定義)。
  • 生成されたクラスの名前を指定する クラス 属性 (定義 名前空間で定義されます)。 1 つ以上のピリオドを含む名前を指定した場合、ビルド システムは名前の前に DefaultClrNameSpace 値を付けません。

例として、HelloWorldApplication.xaml ファイルの内容を次のように変更します。

<NavigationApplication xmlns="https://schemas.microsoft.com/2003/xaml"
                       xmlns:def="Definition"
                       def:Class="Special.MyApp"
                       def:CodeBehind="HelloWorldApplication.xaml.cs" 
                       StartupUri="HelloWorld.xaml" />

生成されるクラスは次のようになります。

namespace Special {
  class MyApp :
           MSAvalon.Windows.Navigation.NavigationApplication {
.
.
.
  }
}

同じクラスでのコードとマークアップの使用

ほぼすべてのアプリケーションでは、UI を指定するマークアップに加えて、ボタンのクリック イベント ハンドラーや仮想メソッドのオーバーライドなどのコードを記述する必要があります。 第 1 章では、ナビゲーション ベース以外のアプリケーションが OnStartingUp メソッドをオーバーロードしてウィンドウとコントロールを作成したことを思い出してください。 この例を書き直して、アプリケーション コードとマークアップを組み合わせる方法を説明します。

この次の例では、ナビゲーション以外のアプリケーションを作成しますが、そのようなアプリケーションを作成する説得力のある理由は本当にないことを強調したいと思います。 別のページに実際に移動しないナビゲーション ベースのアプリケーションをいつでも作成できます。 しかし、このようなアプリケーションを記述するには、コードとマークアップを同じクラスに混在させる必要があるため、良い例を提供します。

ナビゲーション以外のアプリケーションを作成するには、MSAvalon.Windows.Application から継承し、OnStartingUp メソッドをオーバーライドするカスタム クラス 定義する必要があることを思い出してください。 アプリケーション定義ファイルは、プログラムが使用するアプリケーション オブジェクト クラスを宣言します。 そのため、ナビゲーション以外のアプリケーションでは、そのオーバーライドする OnStartingUp メソッドを同じクラスで定義する必要があります。

次の変更を除き、非ナビゲーション アプリケーションのアプリケーション構成ファイルには、ナビゲーション アプリケーションの定義ファイルと同じ項目が含まれます。

  • ルート要素は、NavigationApplicationではなく、Application
  • ファイルには、アプリケーション クラスの OnStartingUp メソッドの実装を含めるか参照する必要があります。

マークアップとコードを使用して 1 つのクラスを実装する必要があるため、ソース コード ファイルを XAML ファイルに関連付ける手法を示す必要があります。

Source-Behind ファイルと XAML ファイルの関連付け

多くの場合、マークアップを使用してアプリケーションの一部を開発し、従来のプログラミング言語を使用して他の部分を開発する必要があります。 次の手法を使用して、UI とロジックを個々のソース ファイルに分離することを強くお勧めします。

XAML CodeBehind 要素 (定義 名前空間で定義) を任意の XAML ファイルのルート要素に追加し、ソース コード ファイルの名前 (分離コード ファイルとも呼ばれます) を指定できます。 ビルド エンジンは、XAML 宣言をマネージド クラスにコンパイルします。 ビルド システムでは、分離コード ファイルもマネージド クラス宣言にコンパイルされます。 難しい点は、これらのクラス宣言の両方が 1 つのクラスの部分宣言を表すということです。

第 1 章の最初の例と同等の非ナビゲーション アプリケーション クラスを生成する XAML 定義を次に示します。

<Application xmlns="https://schemas.microsoft.com/2003/xaml"
             xmlns:def="Definition"
             def:Language="C#"
             def:Class="IntroLonghorn.CodeBehindSample"
             def:CodeBehind="CodeBehind.xaml.cs" />

このアプリケーション定義ファイルには、次の 2 つの注目すべき側面があります。

  • 言語 属性は、分離コード ファイルに C# ソース コードが含まれていることを指定します。
  • CodeBehind 属性は、ソース ファイル名がCodeBehindMySample2.xaml.csされることを指定します。

一致するソースビハインド ファイルを次に示します。

namespace IntroLonghorn {
  using System;
  using MSAvalon.Windows;
  using MSAvalon.Windows.Controls;
  using MSAvalon.Windows.Media;

  public partial class CodeBehindSample {
    MSAvalon.Windows.Controls.SimpleText txtElement;
    MSAvalon.Windows.Window              mainWindow;

    protected override
    void OnStartingUp (StartingUpCancelEventArgs e) {
      base.OnStartingUp (e);
      CreateAndShowMainWindow ();
    }

    private void CreateAndShowMainWindow () {
      // Create the application's main window
      mainWindow = new MSAvalon.Windows.Window ();

      // Add a dark red, 14 point, "Hello World!" text element
      txtElement = new MSAvalon.Windows.Controls.SimpleText ();
      txtElement.Text = "Hello World!";
      txtElement.Foreground = new
       MSAvalon.Windows.Media.SolidColorBrush (Colors.DarkRed);
      txtElement.FontSize = new FontSize (14,
                                          FontSizeType.Point);
      mainWindow.Children.Add (txtElement);
      mainWindow.Show ();
    }
  }
}

分離コード ファイルのクラス宣言の 部分 キーワードに注目してください。 このキーワードは、コンパイラがこのクラス定義を同じクラスの他の定義とマージする必要があることを示します。 これにより、コンパイラが結果のアセンブリ内の 1 つのクラス定義に結合する、個別のソース ファイル内のクラスの複数の部分定義を提供できます。

ソース コードとマークアップを 1 つの XAML ファイルに混在させます

同じファイルにソースコードとマークアップを混在させるのは間違っていると思います。 私もそれを行う方法を示していないと考えた。 しかし、どこかの悪人がこの手法を使用してサンプルプログラムを書くので、彼が何をしたかを理解する必要があるかもしれません。 さらに、前に説明した分離コード ファイルアプローチを使用して、少量の悪の世界を取り除き、UI をロジックから分離することができます。

マークアップと共に直接インラインで挿入されたソース コードを含むアプリケーション定義ファイルを次に示します。

<Application xmlns="https://schemas.microsoft.com/2003/xaml"
    xmlns:def="Definition"
    def:Language="C#"
    def:Class="IntroLonghorn.MySample2" >

  <def:Code>
  <![CDATA[
    protected override void OnStartingUp (StartingUpCancelEventArgs e) {
      base.OnStartingUp (e);
      CreateAndShowMainWindow ();
    }
    . . . Remaining methods elided for clarity
  ]]>
  </def:Code>
</Application>

この例では、言語 属性は、インライン ソース コードが C# であることを指定します。 Code 要素は、インライン ソース コードを含む CDATA ブロックであることに注意してください。 ドキュメントが整形式であることを確認するために、インライン ソース コードを XML CDATA ブロックで囲む必要がある場合があります。 実際、XAML パーサーでは、インライン ソース コードを省略すると整形式のドキュメントが生成される場合でも、常に CDATA ブロックで囲む必要があります。

このような悲惨な思いを示したことをもう一度お詫び申し上げます。

アプリケーション マニフェスト

アプリケーションをコンパイルすると、MSBuild によって、.exe ファイルと 2 つのマニフェスト ファイル (アプリケーション マニフェスト*.manifest、配置マニフェスト *.deploy) が生成されます。 これらのマニフェストは、サーバーからアプリケーションまたはドキュメントを配置するときに使用します。 まず、アプリケーション、すべての依存関係、および 2 つのマニフェスト ファイルをサーバー上の適切な場所にコピーします。 次に、配置マニフェストを編集して、アプリケーション マニフェストの場所を指し示します。

完成度については、アプリケーション マニフェストと配置マニフェストの例を見てみましょう。 次の例に示すアプリケーション マニフェストは、実際には配置マニフェストほど興味深いものではありません。 アプリケーション マニフェストは、単にアプリケーションを構成するすべての部分を定義します。 MSBuild は、アプリケーションをビルドするときにアプリケーション マニフェストを生成します。通常は、その中でほとんどまたは何も変更しません。

HelloWorld.manifest

<?xml version="1.0" encoding="utf-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"
          xmlns:asmv2="urn:schemas-microsoft-com:asm.v2"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd">

  <assemblyIdentity name="HelloWorld" version="1.0.0.0"
                    processorArchitecture="x86" asmv2:culture="en-us"
                    publicKeyToken="0000000000000000" />

  <entryPoint name="main" xmlns="urn:schemas-microsoft-com:asm.v2"
              dependencyName="HelloWorld">

    <commandLine file="HelloWorld.exe" parameters="" />
  </entryPoint>

  <TrustInfo xmlns="urn:schemas-microsoft-com:asm.v2" xmlns:temp="temporary">
    <Security>
      <ApplicationRequestMinimum>
        <PermissionSet class="System.Security.PermissionSet" version="1" 
                       ID="SeeDefinition">
          <IPermission 
            class="System.Security.Permissions.FileDialogPermission"
            version="1" Unrestricted="true" />
          <IPermission 
            class="System.Security.Permissions.IsolatedStorageFilePermission" 
            version="1" Allowed="DomainIsolationByUser" UserQuota="5242880" />
          <IPermission
            class="System.Security.Permissions.SecurityPermission"
            version="1" Flags="Execution" />
          <IPermission
            class="System.Security.Permissions.UIPermission" version="1"
            Window="SafeTopLevelWindows" Clipboard="OwnClipboard" />
          <IPermission
            class="System.Security.Permissions.PrintingPermission"
            version="1" Level="SafePrinting" />
          <IPermission
            class="MSAvalon.Windows.AVTempUIPermission, PresentationFramework,
                   Version=6.0.4030.0, Culture=neutral,
                   PublicKeyToken=a29c01bbd4e39ac5" version="1"
                   NewWindow="LaunchNewWindows" FullScreen="SafeFullScreen" />
        </PermissionSet>

        <AssemblyRequest name="HelloWorld"
                         PermissionSetReference="SeeDefinition" />
      </ApplicationRequestMinimum>
    </Security>
  </TrustInfo>

  <dependency asmv2:name="HelloWorld">
    <dependentAssembly>
      <assemblyIdentity name="HelloWorld" version="0.0.0.0"
                        processorArchitecture="x86" />
    </dependentAssembly>

    <asmv2:installFrom codebase="HelloWorld.exe"
                       hash="5c58153494c16296d9cab877136c3f106785bfab" 
                       hashalg="SHA1" size="5632" />
  </dependency>
</assembly>

アプリケーション マニフェストの内容のほとんどは、比較的明白である必要があります。 entryPoint 要素は、エントリ ポイント メソッドの名前 (メイン) を指定し、エントリ ポイントを含む HelloWorldという名前 依存関係を参照します。 entryPoint 要素には、シェルがアプリケーションを実行するために必要なプログラム名とコマンド ライン引数も含まれています。

HelloWorld依存関係 要素には、依存アセンブリを指定する情報 (dependentAssembly 要素) と、アセンブリのファイルとファイルの元のハッシュを検索する場所をローダーに指示する installFrom 要素が含まれています。 ローダーはハッシュを使用して、コンパイル後にアセンブリに加えられた変更を検出できます。

Longhorn Trust Manager は、TrustInfo 要素を使用して、アプリケーションに必要なセキュリティアクセス許可を決定します。 前の例では、HelloWorld アプリケーションで、SeeDefinition アクセス許可セットに名前を付けた一連のアクセス許可が定義されています。 アクセス許可のセットを定義した直後に、AssemblyRequest 要素は、HelloWorld という名前のアセンブリが、SeeDefinitionという名前のセット内の権限のセット 少なくとも受け取る必要があります。 この例のアクセス許可は、通常、SEE で実行されているアプリケーションに付与されるアクセス許可であるため、Hello World アプリケーションは、セキュリティ警告をユーザーに表示せずに実行されます。

配置マニフェスト

前述のように、配置マニフェストの方が興味深いです。 配置マニフェストには、明らかに、アプリケーションの配置を制御する設定が含まれています。

HelloWorld.deploy

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" 
          xmlns:asmv2="urn:schemas-microsoft-com:asm.v2"  
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd">
  
  <assemblyIdentity name="HelloWorld.deploy" version="1.0.0.0" 
                    processorArchitecture="x86" asmv2:culture="en-us" 
                    publicKeyToken="0000000000000000" />

  <description asmv2:publisher="Wise Owl, Inc." 
               asmv2:product="Brent's HelloWorld Application"            
    asmv2:supportUrl="http://www.wiseowl.com/AppServer/HelloWorld/support.asp" 
  />
  
  <deployment xmlns="urn:schemas-microsoft-com:asm.v2" 
              isRequiredUpdate="false">
    <install shellVisible="true" />
    <subscription>
      <update>
        <beforeApplicationStartup />
        <periodic>
          <minElapsedTimeAllowed time="6" unit="hours" />
          <maxElapsedTimeAllowed time="1" unit="weeks" />
        </periodic>
      </update>
    </subscription>
  </deployment>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity name="HelloWorld" version="1.0.0.0" 
                        processorArchitecture="x86" asmv2:culture="en-us" 
                        publicKeyToken="0000000000000000" />
    </dependentAssembly>
    <asmv2:installFrom codebase="HelloWorld.manifest" />
  </dependency>
</assembly>

配置マニフェストには、Longhorn がアプリケーションをインストールして更新するために必要な情報が含まれています。 配置マニフェストの assemblyIdentity 要素がアプリケーション マニフェストを参照していることに注意してください。 結局のところ、アプリケーション マニフェストには、アプリケーションのすべてのコンポーネントが既に記述されています。 アプリケーションをインストールするには、配置マニフェストに実際には "このアプリケーションをインストールする必要があるファイルの説明があります" と表示されます。

もちろん、アプリケーションをインストールする場合は、システムにコピーするファイルだけでなく、より多くの情報も必要です。 説明 要素には、発行元の、製品、および supportUrl 属性 一覧表示されます。[プログラムの追加と削除] ダイアログ ボックスに内容が表示されます。

deployment 要素は、デプロイ後にアプリケーションをデプロイおよび更新する方法を指定します。 この例では、アプリケーションはシェルに表示され、クライアントのシステムは、ユーザーがアプリケーションを起動するたびに、アプリケーションの新しいバージョンを確認し、必要に応じてダウンロードします。 さらに、システムは定期的に 6 時間おきに 1 週間に 1 回以上、新しいバージョンをチェックします。 定期的なチェックが新しいバージョンを見つけると、Longhornはバックグラウンドで新しいバージョンをダウンロードしてインストールします。これにより、ユーザーが次にアプリケーションを実行する際に実行する準備が整います。

アプリケーションの実行

通常、ユーザーはアプリケーション マニフェストを "実行" して、ローカル コンピューターにアプリケーションをインストールせずに、サーバーから直接アプリケーションを実行します。 Longhorn は、必要に応じてアプリケーションのコンポーネントをダウンロードします。 この場合、アプリケーションを実行するにはサーバーを使用できる必要があります。

ユーザーが配置マニフェストを "実行" すると、Longhorn はローカル コンピューターにアプリケーションをダウンロードしてインストールします。 アプリケーションは、デスクトップにアイコンをインストールし、[スタート] メニュー項目を追加して、通常は従来のインストール済みアプリケーションにすることができます。 もちろん、バックグラウンドの自動更新、バージョンのロールバック、アンインストールのサポートも受けられます。

配置マニフェストを初めて起動すると、Longhorn によってアプリケーションがアプリケーション キャッシュにインストールされ、コントロール パネルの [プログラムの追加と削除] リストにエントリが追加されます。 その後、配置マニフェストを実行するたびに、アプリケーションはアプリケーション キャッシュから直接読み込まれます。 通常、このファイルは再ダウンロードされません。

ただし、コントロール パネルの [プログラムの追加と削除] アプレットを使用してキャッシュからアプリケーションをアンインストールすると、その後配置マニフェストを実行すると、アプリケーションが再度ダウンロードされてインストールされます。

または、サーバー上のアプリケーションのバージョン番号を変更することもできます。 次に、配置マニフェストを実行すると、Longhorn は新しいバージョンを現在のバージョンと並行してダウンロードしてインストールします。 アプリケーションの両方のバージョンは、[プログラムの追加と削除] の一覧に表示されます。

別のビルド システムを作成する理由

私はMSBuildが本当に好きですが、この執筆時点では数週間しか経験していませんでした。 もちろん、メイクファイルの長年の経験は、よりエレガントなビルドシステムを魅力的にします。 現時点では、Make と Ant という 2 つの代替ビルド システムが一般的に使用されています。 MSBuild をこのような代替手段と比較するのは自然なようです。

Make を使用しない理由

多くの開発者が Make という既存のビルド システムに慣れているのに、なぜ新しいビルド システムを開発するのでしょうか。 Make には、ビルド システムへのツールの統合が不十分です。 シェル コマンドを実行するだけです。 このため、ビルド プロセス中に 1 つのツールが別のツールと通信する固有の機能はありません。 MSBuild では、Task クラスのインスタンスが作成され、タスクは通常の .NET 型を渡して互いに通信できます。

メイクファイルには通常とは異なる構文があり、記述が困難であり、大規模なプロジェクトでは複雑になるので、適切にスケーリングされません。 また、Make 以外のツールでは、メイクファイルを簡単に処理することはできません。 MSBuild 以外のツールは、MSBuild プロジェクトの XML ベースの構文を簡単に生成して解析できます。

最後に、Make にはプロジェクトのサポートがありません。 ファイル システムの抽象化はなく、カスケード プロパティもサポートされません。 さらに、メイクファイルを生成するためのデザイン時のサポートはありません。

なぜAntを使用しないのですか?

よく寄せられる質問と同様に、Ant と呼ばれる非常に成功した豊富なシステムが存在する場合に、新しい XML ベースのビルド システムを開発する理由があります。 Ant は、XML ベースのプロジェクト ファイルとタスクをアトミック ビルド操作として開拓した、Apache.org からの Java のオープン ソース ビルド システムです。 nant.sourceforge.netから利用可能なAntと呼ばれるAntの素晴らしい.NETポートもあります。 表面上、MSBuild と Ant/NAnt は似ています。 どちらのツールもプロジェクトのシリアル化形式として XML を使用し、両方のツールはビルド操作のアトミック単位としてタスクを使用します。 どちらのツールにも長所がありますが、詳しく見ると設計目標が異なります。

Ant は、多くの機能を大規模なタスク セットに配置することを設計上の決定にしました。 MSBuild には異なる設計目標があり、同様の機能がエンジンによってカプセル化されます (タイムスタンプ分析、項目を介したタスク間通信、タスクのバッチ処理、項目変換など)。 どちらのアプローチにも長所と短所があります。

Ant のモデルを使用すると、開発者はビルドのすべての詳細を拡張および制御できるため、非常に柔軟です。 ただし、一貫性のある機能を提供するには、タスクをより高度に行う必要があるため、タスク ライターに対する責任も大きくなります。 MSBuild のモデルにより、各タスクが実装する必要がある機能の量が減ります。 そのため、プロジェクト作成者は、さまざまなプロジェクト、ターゲット、タスク間で一貫した機能に依存できます。 さらに、Visual Studio などの統合開発環境では、ビルド プロセス中に呼び出されるタスクの内部について何も知らなくても、一貫性のある結果と豊富なユーザー エクスペリエンスを提供するために、これらのサービスに依存することもできます。

同様に、Ant にはビルド スクリプトの概念は含まれますが、MSBuild に含まれるプロジェクト マニフェストの概念はありません。 ビルド スクリプトには一連のファイルを作成する方法が記述されていますが、ファイルの使用方法を説明する追加のセマンティクスは提供されません。 マニフェストはファイルのセマンティクスをさらに記述します。これにより、IDE などの追加のツールをビルド システムとより深く統合できます。 逆に、プロジェクト マニフェストがないということは、ビルド スクリプトの制約スキーマがないため、開発者が新しい種類の "もの" をビルドするように Ant をより簡単に調整できることを意味します。

概要

これで基本を習得できました。 XAML を記述し、結果のアプリケーションをコンパイル、デプロイ、および実行できます。 残念ながら、これまでに記述することを学んだアプリケーションはかなり退屈です。 第 3 章 XAML の詳細について説明し、Longhorn プラットフォームによって提供されるさまざまな UI オブジェクトの使用方法について説明します。 以降の章では、アプリケーションでも使用できるその他の新しいテクノロジについて説明します。

第 3 章: コントロールと XAMLに進みます。