SourceChord

C#とXAML好きなプログラマの備忘録。最近はWPF系の話題が中心です。

WPF用ライブラリ開発者向けの.NET Core事始め~.NET Core/.NET Framework両対応ライブラリの作成方法~

この記事はC# その2 Advent Calendar 201917日目の記事です。

.NET Core3.0からは、WPFやWinFormsなどのデスクトップアプリ開発もサポートされました。
WPFでのアプリ開発も、徐々に.NET Core環境に移行して行ってもいいかな、、という環境が整いつつあると感じます。

この記事では、WPF向けライブラリ作成という観点から、.NET Core時代のライブラリ作成方法を見ていこうと思います。

.NET Core環境用のWPF向けライブラリ用のプロジェクトテンプレート

VisualStudio 2019の新規プロジェクト作成用テンプレートには、以下のような項目が追加されています。
f:id:minami_SC:20191217224930p:plain

この.NET Core環境向けのWPFライブラリプロジェクトでは、プロジェクトファイルが新しい形式の.csprojファイルになっています。
新しい.csprojのファイル形式は、.NET Framework向けプロジェクトと比べて、以下のようなメリットがあります。

  • NuGetパッケージ作成が簡単
  • .net coreと.net framework両対応のライブラリを作れる

ここでは、「WPF User Control Library(.NET Core)」というテンプレートでプロジェクトを作成し、これらのメリットを順に見ていきます。

.NET Core環境用のWPFクラスライブラリプロジェクト

プロジェクトの新規作成ウィザードで、「WPF User Control Library(.NET Core)」を選び、プロジェクトを作成します。
すると、以下のようなプロジェクトが出来上がります。
f:id:minami_SC:20191217234438p:plain

今回は、ライブラリの内容は特に関係しないので、コードは編集しません。
このプロジェクトの設定を変えながら、色々試していきます。

Nugetパッケージの作成方法

.NET Core環境向けのWPFプロジェクトでは、プロジェクトのプロパティに「パッケージ」というタブが用意されています。
ここに、exe/dllのアセンブリ情報だけでなく、NuGetパッケージに設定する情報も入力できるようになっています。
f:id:minami_SC:20191217225025p:plain
また、ここで「ビルドでNuGetパッケージを生成」にチェックを入れると、ビルドする際にNuGetパッケージも一緒に作ってくれるようになります。

.NET Framework向けのライブラリを作る際は、.nuspecファイルを作ってそこにNuGet用の情報をxmlで書いていました。
プロジェクトの情報がcsprojとnuspecに分散してしまい、ちょっと煩雑だなと思うことも多かったです。

新しいcsproj形式では、この画面で一緒に記入できるのでとても簡単ですね。

そして、プロジェクトをビルドしてみると、ビルド生成物が置かれるフォルダに.nupkgファイルが出来上がります。
f:id:minami_SC:20191218002206p:plain

NuGetで公開したければ、このnupkgをnugetコマンドなどでアップロードすればOKです。

.NET Framework向けにもビルドしてみる

先ほどの手順で、簡単にNuGetパッケージを作ることができました。
ですが、このNuGetパッケージは.NET Core用のパッケージになっており、 旧来の.NET Framework向けのWPFアプリのプロジェクトからは参照することができません。

またプロジェクト設定を開いてみても、以下のように「対象のフレームワーク」が.NET Coreのみとなっており、 .NET Framework4.5などは選択肢として選ぶことができません。
f:id:minami_SC:20191217235034p:plain

csprojファイルの編集

新しいcsproj形式のプロジェクトファイルでも、ファイルをテキストとして直接編集することで、.NET 4.5向けなどに設定を変更することができます。
このライブラリのプロジェクトファイルを、テキストエディタで開いてみます。
以下のような内容となっており、TargetFrameworkという項目でnetcoreapp3.1が指定され、.NET Core3.1向けのビルド設定になってることがわかります。

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

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <UseWPF>true</UseWPF>
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
  </PropertyGroup>

</Project>

これを以下のように変更すると、.NET 4.5向けのビルドができるようになり、.NET4.5環境のWPFアプリでも参照できるライブラリとなります。

<TargetFramework>net45</TargetFramework>

.NET Framework向けにパッケージを作成した場合の問題点

この方法で、.NET 4.5向けに作成したライブラリは、.NET Core環境/.NET Framework環境のどちらのWPFアプリでも利用することができます。

しかし、.NET Core環境で参照した際に、以下のような警告メッセージが表示されるようになってしまいます。
f:id:minami_SC:20191217233849p:plain
f:id:minami_SC:20191217233907p:plain

一応、これでも.NET Core環境のWPFアプリで利用することはできます。
でも、どうせなら.NET Coreにちゃんと対応した形でビルドしたいですよね。

てことで、.NET Core環境向けのWPFライブラリの作り方を見ていきます。

.NET Coreと.NET Framework両対応のライブラリ作成

先ほどは、csprojファイルをテキストと開いて、TargetFrameworkという項目を編集しましたが、
TargetFrameworkという項目をTargetFrameworksという複数形の設定項目に変えると、ビルド対象として、複数のフレームワークを指定できるようになります。
f:id:minami_SC:20191217235104p:plain

csprojのTargetFramework/TargetFrameworks等の項目は、以下のページで説明されています。 https://docs.microsoft.com/ja-jp/dotnet/standard/frameworks

ビルド成果物が保存されるbinフォルダ以下には、それぞれのターゲットフレームワーク名のフォルダが出来上がります。
また、生成されたnupkgファイルをNuget Package Explorerで確認してみると、.NET4.5と.NET Core3.1それぞれのアセンブリが含まれていることが確認できます。
f:id:minami_SC:20191217233928p:plain

このようなNuGetパッケージにしておくと、パッケージ利用者側のプロジェクト構成に合わせて、適切なアセンブリが参照されるようになります。

.NET CoreでWPFが利用できる環境は整いましたが、まだしばらくの間は両方の環境が共存した状況が続くと思います。
ライブラリ作成者の観点では、「様々な環境で使えるライブラリを作りたい」と考えると思いますが、
そんな時には、このような方法で複数ターゲット向けのアセンブリを含んだライブラリを作るとよいのでは、と思います。


さいごに

以下宣伝。
WPFでFluentDesignなルック&フィールのUIを作るための、FluentWPFというライブラリを作っています。

WPFアプリでも、こんな風にアクリル効果の効いたウィンドウや各種ボタンなどのUIが作れます。
f:id:minami_SC:20171226020340g:plain:w300 f:id:minami_SC:20190602171129g:plain:w500

このライブラリでも、今回の記事で紹介した方法で、.NET Coreと.NET Framework両対応なライブラリにしています。
もしよかったら、使ってみてくださいませ♪