LoginSignup
10
5

More than 5 years have passed since last update.

nuget初心者がPlugins for Xamarinを利用して、nugetパッケージを作ってみた

Posted at

はじめに・・

Xamarin向けに以下の要件でライブラリを作る必要がありました。

  • IF部分はPCLじゃなくて、.NET Standard2.0対応してほしい
  • プラットフォーム依存な部分はDIじゃなくて、Plugins for Xamarinみたいな機構を使って欲しい
  • nugetパッケージ化してほしい

ほぅ、、、全然わからんぞ・・。
ということで、四苦八苦しながら、nugetパッケージ化までしたので、やった事とか調べたことを書きます。

Plugins for Xamarin?

そもそも「Plugins for Xamarinってなんぞ?」と思ったので、
google先生に聞きました。

この記事とか本家のページが参考になります。

Plugins for Xamarinは「Xamarin.AndroidやXamarin.iOS向けの固有機能を上手くIF化して、抽象化レイヤーで利用できるようにしたライブラリ」となります。
※ライブラリというかプロジェクトのテンプレートかな。

Plugins for Xamarinのリポジトリはこちら

利用するためにプロジェクトテンプレートをVisual Studio(※1)に取り込む必要があります。
こちらから、テンプレートをダウンロード出来ます。

vsixのため、Visual Studio for Macではインポート出来ません。。(まずここにはまる・・)
Windows版でライブラリ開発はしましょう!って事ですかね・・。

Plugins for Xamarinで試しにプロジェクトを作ってみる

試しに「SamplePlugin」という名前でPlugins for Xamarinのテンプレートを作って、サンプルのプロジェクトを作ると以下の構成になります。

  1. Plugin.SamplePlugin (PCL)
  2. Plugin.SamplePlugin.Abstractions (PCL)
  3. Plugin.SamplePlugin.Android
  4. Plugin.SamplePlugin.iOS ※本当はUWPとかも出来ますが、今回は不要だったので、削除しました。

とりあえず自分が思った感想は、
「ほぅ、、こんな感じなのか。そもそも、これどうやってプラットフォームごとにAPI(の中身)変わってるんだ?」
と思ったので、調べてみました。

Plugins for XamarinのAPI切り替えについて

平たく言うと「Bait and Switch」という仕組み?を使って、APIの切り替え(正確にはdllを切り替え)をしています。

前述したサンプルのプロジェクトを例にあげると、以下のようになっています。
* 2のAbstractionsはIFのみを提供(もしくは抽象化したクラス)
* 1はPCLなプロジェクトから呼び出し可能
* 3はXamarin.Androidなプロジェクトから呼び出し可能
* 4はXamarin.iOSなプロジェクトから呼び出し可能

1.3.4ではIFの実体を提供するCrossSamplePluginというクラスが定義されていて、同じファイルを参照しています。

実体については、ビルド時のオプションで変わるようになっています。
※1の場合は実体はなしとし、3,4の場合はプラットフォームに応じたIFを実装したImplementationクラスを返すようになっている。

その結果何が起こるかというと、1.3.4のdllは全て同じ名前(完全修飾名が同じ)となります。
実行時はプラットフォーム毎に見るDLLを変えることが出来ます。
※上手く説明出来ないので、、こことかここらへんを参考にしてみてください。

Plugins for Xamarinの.NET Standard対応について

さて、ここまででベースとなるプロジェクトは出来ました。
でも、Plugins for Xamarinの抽象化部分(サンプルで言う所の1と2)はPCLで出来ているため、まだ要件をみたせていません。

.NET Standard2.0へ置き換えが必要となります。

.NET Standard?

ここが参考になりました。

PCLを.NET Standard2.0に置き換える

「ふむ、プロパティ変えるだけで済むやろ」
と、思った時期が私にも有りました・・・・涙

単純にプロジェクトのプロパティからTargetFrameworkの変更では出来ませんでした・・。
なので、以下の手順を踏みます

  • プロジェクトファイルをいじって、.NET Standardなプロジェクトに変更する
  • 不要なファイルやフォルダを削除する

ちなみにいじるプロジェクトはサンプルで言う所の1と2になります。
※1と2を.NET Standard2.0にすれば良いです。

プロジェクトファイルの変更

それぞれ以下のように直しました。
※自分は直接いじりましたが、.NETStandardなクラスのプロジェクトを作って、差し替えるほうが楽かもです。

Plugin.SamplePlugin.csproj
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DefineConstants>TRACE;DEBUG;NETSTANDARD2_0;PORTABLE</DefineConstants>
  </PropertyGroup>
  <ItemGroup>
    <!-- A reference to the entire .NET Framework is automatically included -->
    <ProjectReference Include="..\Plugin.SamplePlugin.Abstractions\Plugin.SamplePlugin.Abstractions.csproj">
      <Project>{6edb0588-ffc5-4ef5-8a99-9e241d0f878d}</Project>
      <Name>Plugin.SamplePlugin.Abstractions</Name>
    </ProjectReference>
  </ItemGroup>
</Project>
Plugin.SamplePlugin.Abstractions.csproj
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
    <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DefineConstants>TRACE;DEBUG;NETSTANDARD2_0;</DefineConstants>
  </PropertyGroup>
</Project>

不要ファイルの削除

.NET StandardなプロジェクトではAssemblyInfoとかは不要そうなので、削除しました。
※削除しないとビルドエラーになっちゃう。

nugetパッケージの作成

先程あげたこのページを見ると、Plugins for Xamarinのテンプレートを入れた段階で「Plugins for Xamarin NuSpec」があるらしいのですが、、私は見つからず。。

血の涙を流しながら、一からパッケージを作ろう!と決意しました。

nugetパッケージってどうやって作る?

色々とgoogle先生に聞いて、作ってみました。
こことかここ

簡単な構成のプロジェクトであれば、nuspecを作るまでもなく、実は以下でパッケージ化出来ます。

nuget pack SamplePlugin.csproj

ただ上記だと、Plugins for Xamarinの構成ではパッケージ化しても、上手く動作しません。
※手元でやった感じではダメでした・・。実は出来るのだろうか・・?

そのため、nuspecを書いて、明示的にnugetパッケージの構成を決めるようにしました。

nuspec?

nuspecとは「nugetパッケージ化する際に、どのようにパッケージ化するか?」という情報を記載した仕様ファイルとなります。(たとえば、バージョン情報とか依存関係とか)

今回のサンプルの場合だと以下のようなnuspecファイルを作成しました。

Plugin.SamplePlugin.nuspec

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
  <metadata>
    <id>Plugin.SamplePlugin</id>
    <version>1.0.0</version>
    <title>SamplePlugin</title>
    <authors>shota.sakamoto</authors>
    <owners>shota.sakamoto</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>sample plugin</description>
    <releaseNotes>Test</releaseNotes>
    <copyright>Copyright 2018</copyright>
    <tags>sampleplugin</tags>
    <dependencies>
    </dependencies>
  </metadata>
  <files>
    <!-- Cross-platform reference assemblies -->
    <file src="Plugin.SamplePlugin\bin\Debug\netstandard2.0\Plugin.SamplePlugin.dll" target="lib\netstandard2.0\Plugin.SamplePlugin.dll" />
    <file src="Plugin.SamplePlugin\bin\Debug\netstandard2.0\Plugin.SamplePlugin.deps.json" target="lib\netstandard2.0\Plugin.SamplePlugin.deps.json" />
    <file src="Plugin.SamplePlugin.Abstractions\bin\Debug\netstandard2.0\Plugin.SamplePlugin.Abstractions.dll" target="lib\netstandard2.0\Plugin.SamplePlugin.Abstractions.dll" />
    <file src="Plugin.SamplePlugin.Abstractions\bin\Debug\netstandard2.0\Plugin.SamplePlugin.Abstractions.deps.json" target="lib\netstandard2.0\Plugin.SamplePlugin.Abstractions.deps.json" />

    <!-- iOS reference assemblies -->
    <file src="Plugin.SamplePlugin.iOS\bin\iPhone\Debug\Plugin.SamplePlugin.dll" target="lib\xamarinios\Plugin.SamplePlugin.dll" />
    <file src="Plugin.SamplePlugin.Abstractions\bin\Debug\netstandard2.0\Plugin.SamplePlugin.Abstractions.dll" target="lib\xamarinios\Plugin.SamplePlugin.Abstractions.dll" />

    <!-- Android reference assemblies -->
    <file src="Plugin.SamplePlugin.Android\bin\Debug\Plugin.SamplePlugin.dll" target="lib\MonoAndroid\Plugin.SamplePlugin.dll" />
    <file src="Plugin.SamplePlugin.Abstractions\bin\Debug\netstandard2.0\Plugin.SamplePlugin.Abstractions.dll" target="lib\MonoAndroid\Plugin.SamplePlugin.Abstractions.dll" />
  </files>
</package>

このnuspecを使って、一応パッケージ化出来ました!

最後に

今回やってみて、nugetパッケージ化するまで結構はまったので、
情報共有の意味も込めて、記事にしました。

10
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
5