新しい csproj に負けないレガシーな心を持ち続けて云々
Sdk="Microsoft.NET.Sdk"
なプロジェクトファイルで使える小ネタ集です。
NETStandard.Library への参照をいじる
PackageReference を何ひとつ書かなくても NETStandard.Library を勝手にダウンロードしてくるのは、手軽にコードが書けるという点ではいいかもしれないけれど、やはり無駄なパッケージ参照があるというのは許せないものなので、消していきましょう。
DisableImplicitFrameworkReferences
というプロパティがあり、これを true にするとデフォルトの参照が消えます。デフォルトの参照は以下の通り(targets ファイルを漁るとでてくる)で、これらが全部消えます。つまり .NET Framework なら mscorlib だけ、 .NET Core なら無です。
- .NETStandard (Microsoft.NET.Sdk.DefaultItems.props)
- NETStandard.Library 1.6.1
- .NETCoreApp (Microsoft.NET.Sdk.DefaultItems.props)
- Microsoft.NETCore.App 1.0.4 or 1.1.1
- .NETFramework (Microsoft.NET.Sdk.BeforeCommon.targets)
NETStandard.Library のバージョンは NetStandardImplicitPackageVersion
プロパティを、 Microsoft.NETCore.App のバージョンは RuntimeFrameworkVersion
プロパティを書き換えることで、自由に変更することができます。
netcoreapp1.0 をターゲットにすると Microsoft.NETCore.App のバージョンは 1.0.4 になるけど、 1.1.1 に変えても問題なく動くんだよな……。
サンプルコードとして、 NETStandard.Library を消して、 System.Console (とその依存パッケージ)だけを参照するプロジェクトです。
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>netstandard1.4</TargetFramework> <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences> </PropertyGroup> <ItemGroup> <PackageReference Include="System.Console" Version="4.3.0" /> </ItemGroup> </Project>
Portable Class Library や Xamarin クラスライブラリをビルドする
プロジェクトファイルにちょっと手を加えれば、インストールされているフレームワークなら何でもビルドできます。たぶん。
TargetFramework
, TargetFrameworkIdentifier
, TargetFrameworkVersion
、あとプロファイル指定が必要なら TargetFrameworkProfile
というプロパティを設定すれば、勝手にアセンブリ解決してビルドしてくれます。
例えば、いにしえのフレームワーク軍を相手する portable40-net40+sl5+win8+wp8+wpa81
ならこんな感じ
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>portable40-net40+sl5+win8+wp8+wpa81</TargetFramework> <TargetFrameworkIdentifier>.NETPortable</TargetFrameworkIdentifier> <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkProfile>Profile328</TargetFrameworkProfile> </PropertyGroup> <ItemGroup> <Reference Include="System" /> </ItemGroup> </Project>
mscorlib 以外は勝手に参照されないので、必要に応じて Reference を書いてあげる必要があります。
Xamarin も同様にできますが、ファサードアセンブリを使うために ImplicitlyExpandDesignTimeFacades
プロパティを true にしておく必要があるのと、 Visual Studio 2017 からアセンブリの場所が変わったので、それに対する対応を入れる必要があります。
Visual Studio 2015 までは C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework
に Xamarin のアセンブリがありましたが、 2017 では C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\ReferenceAssemblies\Microsoft\Framework
になりました。 Microsoft.NET.Sdk では前者のパスを探しにいくので、 2017 だけがインストールされている環境ではアセンブリが見つかりません。
その対策が入っている Xamarin.Android.Sdk.props をパクりつつ、 Xamarin クラスライブラリをつくるプロジェクトファイルはこんな感じになります。
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>monoandroid70</TargetFramework> <TargetFrameworkIdentifier>MonoAndroid</TargetFrameworkIdentifier> <TargetFrameworkVersion>v7.0</TargetFrameworkVersion> <TargetFrameworkRootPath Condition="'$(VsInstallRoot)' != ''">$(VsInstallRoot)\Common7\IDE\ReferenceAssemblies\Microsoft\Framework\</TargetFrameworkRootPath> <ImplicitlyExpandDesignTimeFacades>true</ImplicitlyExpandDesignTimeFacades> </PropertyGroup> <ItemGroup> <Reference Include="Mono.Android" /> </ItemGroup> </Project>
Xamarin Android プロジェクトで、このプロジェクトを参照に加えて実行してみましたが、問題なく動作しました。
VsInstallRoot
プロパティは Visual Studio についている MSBuild でしか設定されていないので、 .NET Core SDK の MSBuild でビルドした場合には 2015 までのアセンブリの場所を見に行きます。