Visual Studio for Mac環境下でXamarin.Formsを.NETStandard2.0のプロジェクトで使ってみる

現時点（2017年11月18日）でリリースされているVisual Studio for Mac(Stable 7.2.0.636, Alpha 7.3.0.764)では，Xamarin.Formsを使ったアプリケーションを.NETStandard2.0で開発するテンプレートが用意されていない&選択することが出来ません．

しかし最近リリースされたWindows版のVisual Studioではどうもプロジェクトの作成段階で選択できるようになっているようです．（Preview版のみ？）
[.NET Standard Comes to Xamarin.Forms Project Templates!](https://blog.xamarin.com/net-standard-comes-xamarin-forms-project-templates/)

またMacは取り残される運命なのか...と悲観してはいけません．少し工夫することにより.NETStandard2.0で開発することが出来ます．
実際に手を動かしてPCLから.NETStandard2.0へ移行してみましょう．

## プロジェクトの作成

まずは空のプロジェクトを作ってみましょう．
今回はXamarin.FormsのBlank Forms AppのPCLプロジェクトを作成しました．

プロジェクト作成時の初期状態は以下のようになっています．

```
.
├── Droid/
│   └── 今回は無視
├── XamSample/
│   ├── App.xaml
│   ├── App.xaml.cs
│   ├── Properties/
│   ├── XamSample.csproj
│   ├── XamSamplePage.xaml
│   ├── XamSamplePage.xaml.cs
│   ├── bin/
│   ├── obj/
│   └── packages.config
├── XamSample.sln
├── iOS/
│   └── 今回は無視
└── packages/
	 ├── Android関係のパッケージとか
	 └── Xamarin.Forms.2.4.0.280/
```

初期はPCLでのプロジェクトなので，packages.configベースのパッケージ管理のものになっています．
このベースのプロジェクトを元に進めていきます．

## .NETStandard2.0なcsprojへ変更

PCLの状態のcsprojはこんな感じになっています（一部抜粋）．

```
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{A9D65E28-C4B7-45AD-9947-44B5C6FD75A9}</ProjectGuid>
    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
    <UseMSBuildEngine>true</UseMSBuildEngine>
    <OutputType>Library</OutputType>
    <RootNamespace>XamSample</RootNamespace>
    <AssemblyName>XamSample</AssemblyName>
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
    <TargetFrameworkProfile>Profile111</TargetFrameworkProfile>
  </PropertyGroup>
  <ItemGroup>
    <EmbeddedResource Include="App.xaml" />
    <EmbeddedResource Include="XamSamplePage.xaml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="App.xaml.cs">
      <DependentUpon>App.xaml</DependentUpon>
    </Compile>
    <Compile Include="XamSamplePage.xaml.cs">
      <DependentUpon>XamSamplePage.xaml</DependentUpon>
    </Compile>
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <ItemGroup>
    <Reference Include="Xamarin.Forms.Core">
      <HintPath>..\packages\Xamarin.Forms.2.4.0.280\lib\portable-win+net45+wp80+win81+wpa81\Xamarin.Forms.Core.dll</HintPath>
    </Reference>
    <Reference Include="Xamarin.Forms.Platform">
      <HintPath>..\packages\Xamarin.Forms.2.4.0.280\lib\portable-win+net45+wp80+win81+wpa81\Xamarin.Forms.Platform.dll</HintPath>
    </Reference>
    <Reference Include="Xamarin.Forms.Xaml">
      <HintPath>..\packages\Xamarin.Forms.2.4.0.280\lib\portable-win+net45+wp80+win81+wpa81\Xamarin.Forms.Xaml.dll</HintPath>
    </Reference>
  </ItemGroup>
  <ItemGroup>
    <None Include="packages.config" />
  </ItemGroup>
  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
  <Import Project="..\packages\Xamarin.Forms.2.4.0.280\build\portable-win+net45+wp80+win81+wpa81\Xamarin.Forms.targets" Condition="Exists('..\packages\Xamarin.Forms.2.4.0.280\build\portable-win+net45+wp80+win81+wpa81\Xamarin.Forms.targets')" />
</Project>
```

うん，長い．

またこのcsprojのItemGroupを見ると_packages.config_を参照しているので，こちらも見てみましょう．

```
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Xamarin.Forms" version="2.4.0.280" targetFramework="portable45-net45+win8+wpa81" />
</packages>
```

現時点PCLのプロジェクトが参照しているライブラリは_Xamarin.Forms 2.4.0.280_だけということがわかりますね．

これを.NETStandard2.0のプロジェクトに移行してみましょう．
まず始めに参照しているライブラリのバージョンを控えます．と言っても_packages.config_を丸パクリするだけなので特に頑張る必要もありません．

次にcsprojファイルをいじります．

以下のようにします．

```
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>
  
  <ItemGroup>
    <PackageReference Include="Xamarin.Forms" Version="2.4.0.280" />
  </ItemGroup>
</Project>
```

ここの_PackageReference_には対象のライブラリの記述します．


以上です．

__以上です．__

### 補足

実際は_Properties/AssemblyInfo.cs_も削除しています．どうもバージョンの書き方のフォーマットが違う...そうです．
また上記の変更はXamarin.Forms 2.4.x以降を対象としています．

2.3.5-Pre~ の場合はここにxamlのビルドに関する記述が必要となります．
こちらについてはnuitsさんがまとめた記事をごらんください．
[Xamarin（Formsもね）で.NET Standard 2.0なライブラリを利用する](http://www.nuits.jp/entry/xamarin-forms-with-netstandard-20)


## まとめ

GUIから出来ることは現時点限られているので，自分でいい感じに書き換えることで.NETStandard2.0対応のプロジェクトを作ることが出来ます．

実際に手を動かして試してみてください．

.NETStandard2.0で作成したサンプルアプリがこちらなので，こちらも参考にしてみてください．

[yamachu/TonpeiFes2017](https://github.com/yamachu/TonpeiFes2017)

## 記事の元ネタ

[Visual Studio for Macで netstandard 2.0なプロジェクトでXamarin.Formsを使ってみる](http://teitoku-window.hatenablog.com/entry/2017/10/13/113208)
こういうハックで可能になるまでにどのような変遷を辿ってきたかのことがちょっと書いてあります．
記事に書いてあるようにあるStableにおいても最新に近いVisual Studio for Macでないと諸々の不具合が出てしまいます．