次の方法で共有



July 2016

Volume 31 Number 7

Essential .NET - Visual Studio 2015 と .NET Core ツール

Mark Michaelis

Mark Michaelisいよいよ .NET Core RC2 の登場です。RC1 Beta が「リリース候補」と見られていましたが、実は RC2 が真のリリース候補です (RC1 をリリース候補と見ていた方は、RC1 リリース後に行われたすべての変更点をご確認ください)。.NET Core を中心とする開発で重視され強調されていたのは、もちろん、クロス プラットフォーム機能についてです。新しい .NET API だけでなく、付属のランタイムやツールセットでも、Linux や Mac OS X のサポートに重点が置かれています。Visual Studio Code は言うまでもなく、DOTNET.EXE (以前の DNX、DNVM、DNU) などのツールは、マイクロソフト以外の開発者に、.NET を利用するチャンスと最高の開発エクスペリエンスを提供することを目的としていました。

これは大変素晴らしいことです。実際、驚くべきことでもあります。しかし、長年のマイクロソフト開発者にとってはどのような意味があるのでしょう。 今後も続く Windows と Visual Studio の開発に、.NET Core プロジェクトはどのようにかかわってくるのでしょう。 今回は、 .NET Core のさまざまなプロジェクトの種類を取り上げます。また、新しい種類のファイルとその機能について詳しく説明します。新しいプロジェクト構造についても調べます。この構造により、プロジェクトから参照するオープン ソースの NuGet パッケージをサイドバイサイドでデバッグできるようになり、ソース コードにステップ インすることもできます。

作業の開始

.NET Core RC2 の利用を開始するには、当然、新しいプラットフォームをサポートするようにツール (この場合は Visual Studio 2015) を更新します。更新には、2 つの基本的な手順が必要です。

  1. microsoft.com/net/core#windows (英語) から .NET Core Tooling Preview 1 for Visual Studio 2015 をダウンロードします (このページに手順も記載されています)。
  2. bit.ly/27Rmeaj から NuGet パッケージ マネージャーをインストールします。

Visual Studio 2015 をインストールしていることが前提です。インストールしていない場合は、visualstudio.com から無料の Visual Studio Community Edition を入手できます。

新しいプロジェクトの種類

Visual Studio のツールをすべてインストールすると、[新しいプロジェクト] ウィザードを使用してプロジェクトを作成できます (図 1 参照)。

Visual Studio .NET Core のプロジェクト テンプレート
図 1 Visual Studio .NET Core のプロジェクト テンプレート

ご覧のように、プロジェクトの種類は 4 つあります。(1 つは、Visual C#\Web フォルダーと Visual C#\.NET Core フォルダーの両方に含まれているため、2 回表示されます)。

言うまでもなく、各プロジェクトの種類が生成するファイルのセットは異なります (図 2 参照)。

図 2 Visual Studio のプロジェクトの種類それぞれに含まれるファイル

ファイル名 Class Library Console Application ASP.NET Core Web Application (.NET Core) ASP.NET Core Web Application(.NET Framework)
app.config       X
Properties\AssemblyInfo.cs X X    
Class1.cs X      
Global.json X X X X
Properties\launchSettings.json     X X
Program.cs   X X X
Project.json X X X X
Project.lock.json X X X X
Project_Readme.html     X X
<プロジェクト>.xproj     X X
<プロジェクト>.xproj.user     X X
Startup.cs     X X
Web.config     X X

App.config は、オプションの構成ファイルです。.NET Framework 1.0 から使用してきた <アプリ名>.config と同様のファイルです。以下のコードは、既定のファイルを示しています。ここでは、サーバー ベースのガベージ コレクションを使用するか、クライアント/ワークステーション型のガベージ コレクションを使用するかを識別しています (詳細については、https://msdn.microsoft.com/ja-jp/library/ms229357(v=vs.110).aspx を参照してください)。

<configuration>
  <runtime>
    <gcServer enabled="true"/>
   </runtime>
</configuration>

AssemblyInfo.cs は、構成、会社、製品、商標など、アセンブリ データを特定します。これは、2000 年に .NET が最初にリリースされて以来 Visual Studio .NET プロジェクトに含まれている標準の AssemblyInfo.cs ファイルです。

Class1.cs は、Class1 クラスのスケルトン C# クラス ファイルで、既定のコンストラクターが含まれています。

Global.json は、.NET Core プロジェクトの初回作成時に [ソリューションのディレクトリを作成] を選択すると、自動生成されます。後ほど説明するように、projects ノードで、デバッグ時にソース コードの追加の場所を特定します。

LaunchSettings.json は、Web ホストのさまざまな構成設定を特定します。構成設定には、デバッグ用のアプリケーション URL、存在する場合は IIS ホスト (IIS Express など)、起動前に設定する環境変数、SSL や認証などがあります。環境変数は、.NET Core Configuration が環境 (development、test、production) を特定するために使用します。Visual Studio のプロジェクトのプロパティ ウィンドウにある [デバッグ] タブから変更を行うと、launchSettings.json ファイルを編集する UI が表示されます (図 3 参照)。

Visual Studio のプロジェクトのプロパティ ウィンドウにある [デバッグ] タブ
図 3 Visual Studio のプロジェクトのプロパティ ウィンドウにある [デバッグ] タブ

図 4 に、launchSettings.json のサンプル ファイルを示します。

図 4 launchSettings.json のサンプル ファイル

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:43799/",
      "sslPort": 0
    }
  },
  "profiles": {
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "WebApplication1NetFramework": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

Project.json は新しいプロジェクト ファイルです。このファイルの機能は *.*PROJ ファイルの機能の大部分と重複します。ここでは、プロジェクト参照や、バージョン番号のようなビルド オプションなどを特定し、.NET Core と .NET Framework のどちらのプラットフォームをターゲットにコンパイルするかなどを特定します。詳しくは、この後説明します。

Project.lock.json は、コンパイルに必要なファイルの一覧 (通常は、NuGet 参照) を格納します。ここにはパッケージの具体的なバージョン番号を含みます。これは、ワイルドカードをサポートする project.json ファイルとは異なります。project.lock.json がないと、パッケージ全体の復元が行われます。Project.lock.json には、ローカルにダウンロード (復元) しているパッケージに関連する他のデータと合わせて、パッケージ グラフが含まれます。通常、このファイルはチェック インされず、ファイルが存在しないときは、NuGet パッケージの復元を実行することによって作り直されます。このファイルは、Visual Studio 内では project.json の子ノードとして一覧されます。

ClassLibrary.xproj は、既製の MSBuild ファイルです。ここでは、プロジェクトのビルド時に行うことを定義します。最新バージョンでは、Microsoft.DotNet.targets をインポートします。これは、新しい DotNet.exe コマンドを利用するビルド タスクを定義します。以前の MSBuild proj ファイルとは異なり、xproj ファイルは、(今のところ) ほとんどの情報が project.json に移行されているため、驚くほど小さくなっています。

ClassLibrary.xproj.user は ClassLibrary.xproj ファイルよりも優先され、(ポートのような) ローカル ユーザーのデバッグ固有の設定など、追加の MSBuild プロパティを指定します。通常、このファイルはユーザー固有で、Visual Studio 内からは可視にならないため、チェック インされません。

Program.cs はProgramクラスを定義します。たとえば、アプリケーション (Web アプリケーション) の Main エントリ ポイントなどを定義します。

Web.config は IIS の最小構成を指定します。たとえば、Web ホスト プロセスを検索する場所の指示、すべてのトラフィックをこのプロセスにリダイレクトする構成などを含めます。以下のコードに例を示します。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule"
        resourceType="Unspecified"/>
    </handlers>
    <aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%"    
      stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout"
      forwardWindowsAuthToken="false"/>
  </system.webServer>
</configuration>

web.config にはアプリの設定が含まれなくなりました。2016 年 2 月のコラム「.NET Core における構成」(https://msdn.microsoft.com/ja-jp/magazine/mt632279.aspx) で説明したように、これらの設定は Microsoft.Extensions.Configuration によって読み込まれる構成ファイルに移行されています。

Visual Studio が作成する .NET Core のすべてのプロジェクトの種類では、プロジェクトの新規作成時に [ソリューションのディレクトリを作成] オプションを選択しているため、すべてのソース コードがソリューションの src サブディレクトリに格納されます。また、テスト プロジェクトは、src と共に tset ディレクトリに配置されるものと想定されています (ただし、.NET Core Tooling Preview 1 for Visual Studio 2015 リリースの既定の設定では、この処理は行われません)。他にも、builds や docs のようなディレクトリが考えられます (個人的には、テスト プロジェクトをまったく別のツリーに配置するよりも、テスト中のターゲット プロジェクトと一緒に配置する方が望ましいと考えていますが、これはマイクロソフトが推奨する既定のソリューション構造ではありません。経験上、できる限り既定の設定を利用することをお勧めします)。

Project.json の詳細

.NET Core の新しいプロジェクト構造で最も重要なファイルは、おそらく project.json です。このファイルは以下を目標に設計されています。

  • NuGet ファイル マネージャーの package.config ファイルを置き換え、プロジェクトの NuGet 参照を特定します。
  • プロジェクトがサポートするフレームワークと、特定のフレームワーク向けにプロジェクトをビルドする方法を示した構成の詳細を指定します。
  • 自己完結型アプリのターゲット プラットフォームを特定します。自己完結型アプリは、ターゲット プラットフォームに必要なプラットフォーム固有の .NET Core ランタイムなどの依存関係をすべて含みます。プロジェクトがポータブル アプリの場合は、アセンブリを実行するターゲット コンピューターにインストールされていることを想定するフレームワークを特定します。

この 3 つの設計目標は、project.json の 4 つの主要セクションに分散されています (プロジェクトの種類によって機能が重複する runtimes と supports は組み合わせています)。

dependencies: プロジェクトが依存する各 NuGet パッケージを一覧します。たとえば、一覧する依存関係のバージョン番号などです。バージョン番号にはワイルド カードを指定できます。そのため、NuGet パッケージ マネージャーの復元によって、ワイルド カードに一致する「最新バージョン」を自動的にダウンロードできます。バージョン番号に引用符のペアだけを指定して、「利用可能な最新バージョン」を示します。 さらに、Visual Studio の NuGet パッケージ マネージャー ウィンドウから参照を追加することもできます。また、パッケージ ソースまたはフィードを構成するときに、Visual Studio が非同期に読み込む IntelliSense を利用して、入手可能なパッケージを指定することもできます (図 5 参照)。IntelliSense は、パッケージ名とバージョン番号のどちらでも機能します。

利用可能なパッケージとバージョンの一覧を動的に読み込む IntelliSense
図 5 利用可能なパッケージとバージョンの一覧を動的に読み込む IntelliSense

frameworks: プロジェクトを実行するフレームワークを特定します。たとえば、net45、netstandard1.5、net40 などを指定します。また、特定したフレームワークに対してアプリに固有の設定も指定できます。その場合は、buildOptions、dependencies、frameworkAssemblies、imports などを指定します。たとえば、.NET 45 実行環境に対してアンセーフ コードを許可するには、frameworks 要素内で以下のように指定します。

"net45": {"buildOptions": {"allowUnsafe": true}}

runtimes/supports: project.json が runtimes または supports を使用するかどうかは、プロジェクトがポータブル アプリまたは自己完結型アプリのどちらをターゲットとするかによって異なります。自己完結型アプリの場合、runtimes セクションはサポート対象の OS を特定します。つまり、アプリにバンドルするランタイム ライブラリを特定します。自己完結型アプリは、(少なくとも .NET に関する限り) ターゲット コンピューターにプレインストールされているものとの依存関係は生じません。

これに対して supports セクションは、ポータブル アプリの場合、アプリ起動時に検索するランタイムの依存関係を特定します。検索する依存関係を 1 つ特定すれば十分です。この一覧はここで指定しなくてもかまいません (別の場所でも実行できます)。ただし、supports 要素を指定すると、NuGet がすべての依存関係が満たされていることをチェックすることになります。

project.json は RC1 でも RC2 でも重要な役割を担っています。ですが、皮肉なことに RC2 のリリース後間もなく、.NET Core チームと ASP.NET チームは、project.json が十分に確立された MSBuild プロジェクト ファイルに対して冗長だと判断しました。MSBuild プロジェクト ファイルでは、構成、ビルドの依存関係、ビルド ターゲット、コンパイル フラグ、コマンドラインと環境変数のプロパティ設定、ビルド コマンドなど、既に多くの重要な機能をサポートしています。チームはすべてを見直すのではなく、最初に project.json ファイルを作成するきっかけとなったことを復習し、*.*PROJ ファイルが大きくなりすぎることがきっかけだったことを思い出しました。 *.*PROJ ファイルはグロビング パターン (ワイルド カード) を使用しないで、プロジェクト内のすべてのファイルを個別に一覧していたため大きくなる傾向がありました。ファイルが大きくなりすぎると、開発者がビルド前にこのファイルを開いて確認することはほとんどなくなり、望まないコマンドがファイルに紛れ込んでしまってもわかりません。チームは、まったく新しいビルド ファイルを作成するのではなく、*.*PROJ ファイルが大きくなりすぎるのを解決することに決め、これを編集するコマンドラインユーティリティを用意しました。project.json にあって *.*PROJ ファイルに唯一ないのが、JSON 構文です (ただし、JSON は現代風の XML にすぎません。これは、XML がその当時の現代風のフラット ファイルや INI ファイルだったのと同じです)。 project.json 廃止の可能性については、2016 年 5 月 10 日の ASP.NET Community Standup での Damian Edwards による声明とそれに対応する Alexandre Mutel による投稿 (bit.ly/1NJ9r31、英語)、および Willem Meints がまとめたブログ記事 (bit.ly/1sJc2An、英語) をご覧ください。

パッケージのソース コードのデバッグ

最も期待している機能の 1 つが、パッケージのデバッグとパッケージへのステップ インに対する新しいサポートです。場合によっては、パッケージのソース コードを変更することもできます。たとえば、さまざまなチームが共有する全社規模の「フレームワーク」アセンブリがあるとします。ただし、このフレームワークのパッケージは基本的にはオープン ソースなので、社員全員 (場合によっては社外メンバー) が機能強化と変更に関与できます。ここで、このフレームワークの NuGet パッケージを参照していて、ある時点でこのパッケージにバグがあるかもしれないと疑われる事態になったとします。このバグは解決する必要があるか、機能強化が必要です。通常、機能強化や変更を行うには、担当するプロジェクトやソリューションとは別のコンポーネントのソース コードに取り組む必要があります。そのような取り組みを必要としないで、そのソース コードをダウンロードし、主担当の開発と並行した統合型エクスペリエンスとしてソース コードを更新できるとしたらどうでしょう。そのうえ、シンボル サーバーや PDB ファイルを必要としないで、そのコードにステップ インできるとしたらどうでしょう。 これが今回 Visual Studio 2015 で実現されるシナリオです。

たとえば、GitHub で入手できる Microsoft.Extensions.Logging パッケージをデバッグするとします。プロジェクト内でパケージを追加してデバッグするには、(おそらく git clone コマンドまたは git submodule コマンドを使用して) ソース コードをダウンロードします。次に、Visual Studio にそのソース コードの検索場所を認識させるために、たとえば、監視対象のディレクトリ一覧に "submodules\Logging" を追加するなどして、global.json の projects ノードを編集します。

{
  "projects": [ "src", "test", "submodules\Logging" ],
  "sdk": {
    "version": "1.0.0-*"
  }
}

もちろん、(コードをサブディレクトリにコピーしていない場合などは) フルパスを指定できます。ただし、ディレクトリの区切り記号には、2 つのバック スラッシュ (\\) または単一のスラッシュのいずれかを使用します (例、c:/users/mark/documents/visual studio2015/Projects/Microsoft.Extensions.Logging)。

global.json を更新、保存後、Visual Studio がソース コードを正しく見つけると、自動的にプロジェクトがソリューションに追加され、ソース コードをデバッグできるようになります。

ソース コードを読み込むディレクトリは、以下のように非常に単純なアルゴリズムで判断されています。

  1. global.json で指定されているソース コードの場所にパッケージと同じ名前 (Microsoft.Extensions.Logging など) のフォルダーが含まれていて、そのフォルダーに project.json という名前のファイルが含まれていれば、デバッガーは、そのフォルダーとそのフォルダー内のソース ファイルを使用します。
  2. それ以外の場合は、packages フォルダーからコンパイル済みバイナリを読み込みます。

詳細については、「Visual Studio 2015 を使用して ASP.NET 5 フレームワークのコードをデバッグする」(bit.ly/22niJ7w、英語) を参照してください。

まとめ

.NET Core をまだ使ったことがない方は、今すぐ始めれば、短時間で大きな学習効果が得られます。以前のバージョンからのアップグレードをご検討の開発者の方も、すぐにアップグレードされることをお勧めします。いずれアップグレードするのであれば、早く始めるほど新しい機能を早く習得できます。


Mark Michaelis は、IntelliTect の創設者で、同社でチーフ テクニカル アーキテクト兼トレーナーを務めています。彼は約 20 年間 Microsoft MVP に認定され、2007 年から Microsoft Regional Director を務めています。Michaelis は、C#、Microsoft Azure、SharePoint、Visual Studio ALM など、マイクロソフト ソフトウェアの設計レビュー チームにも所属しています。開発者を対象としたカンファレンスで講演を行い、多数の書籍を執筆しています。最近では、『Essential C# 6.0 (5th Edition)』(Addison-Wesley Professional、2015 年) を執筆しました (itl.tc/EssentialCSharp、英語)。連絡先は、Facebook (facebook.com/Mark.Michaelis、英語)、ブログ (IntelliTect.com/Mark、英語)、Twitter (@markmichaelis、英語)、または電子メール mark@IntelliTect.com (英語のみ) です。

この記事のレビューに協力してくれた IntelliTect の技術スタッフの Kevin Bost、Andrew Scott、および Michael Stokesbary に心より感謝いたします。