C# のアセンブリ情報は AssemblyInfo.cs によって制御されています。 .NET Core でいくぶん取り扱いが変わったものの基本は一緒です。
たびたび忘れるので、どのように取り扱いが変わったのか制御方法をメモしておきます。
目次
- 目次
- TL;DR
- Microsoft.NET.GenerateAssemblyInfo.targets
- AssemblyInfo の自動生成をなぜ制御するのか
- AssemblyInfoの自動生成を止める
- AssemblyInfo の特定の属性の生成を止める
TL;DR
- .NET Core で AssemblyInfo.cs はビルド時に自動生成されるようになりました
- csprojにGenerateAssemblyInfoを指定することで自動生成自体を止めたり、GenerateAssemblyXxxxxAttributeを指定することで特定属性の出力を止めることができます
- 出力を上書きたいときは、上書きたい属性だけ制御するようにして予期せぬ副作用は回避しましょう
Microsoft.NET.GenerateAssemblyInfo.targets
AssemblyInfo は、.NET Framework まではProperties/AssemblyInfo.cs
として存在していましたが、.NET Core SDK ベースのcsproj ではビルド時に自動生成されるようになりました。
この自動生成を制御しているMSBuildのタスク Microsoft.NET.GenerateAssemblyInfo.targets
を見つつどのように行うか見ていきましょう。
sdk/Microsoft.NET.GenerateAssemblyInfo.targets at master · dotnet/sdk
AssemblyInfo の自動生成をなぜ制御するのか
自前でAssemblyInfoを生成しようとしたときに、属性が重複してビルドできなくなるためです。
例えば、.NET Core の適当なプロジェクトを作って次のようにアセンブリのバージョンを任意の値で制御しようとするとエラーが起こります。
エラーは次の通りです。
Error CS0579 Duplicate 'System.Reflection.AssemblyVersionAttribute' attribute
このような時に、AssemblyInfo の出力を制御したくなります。
AssemblyInfoの自動生成を止める
dotnet core のプロジェクトでビルドをすると、obj フォルダの中にASSEMBLYNAME.AssemblyInfo.cs
が自動生成されます。
ASSEMBLYNAME は、デフォルトではプロジェクト名ですがご存知の通り指定もできます。(ここでは省きます)
先ほどの Microsoft.NET.GenerateAssemblyInfo.targets
から、次の属性で制御されていることがわかります。
<PropertyGroup Condition="'$(GenerateAssemblyInfo)' == 'true'">
AssemblyInfo の自動生成を止めたいプロジェクトのcsproj に次の要素を書くことで、objに生成されなくなります。
<PropertyGroup> <GenerateAssemblyInfo>false</GenerateAssemblyInfo> </PropertyGroup>
例えば先ほどのConsole アプリのcsproj を編集してみましょう。(上:編集前 Before.csproj / 下:編集後 After.csproj)
これでAssebly属性の重複によるビルドエラーが解消して、ビルドができるようになりました。 先ほどまであったConsoleApp2.AssemblyInfo.cs が obj フォルダに生成されなくなったことが確認できます。
ただし、AssemblyInfo の自動生成を止めると副作用が大きいため推奨しません。
特に、ASP.NET Core や .NET Core で UserSecrets を使っている場合は、UserSecretsが機能しなくなります。 これは、UserSecrets が実行時にsecret のパスを参照するときにSecret Id はAssemblyInfo にビルド時に埋め込むようにしており、自動生成を止めるとUserSecrets の Id も参照できなくなるためです。
AssemblyInfo の特定の属性の生成を止める
先ほどのようにただバージョンを指定したものにするなら、AssemblyInfoは生成するけど、特定の属性をとめるほうが副作用がありません。
これは先ほどの Microsoft.NET.GenerateAssemblyInfo.targets
から、次の属性で制御されていることがわかります。
例えば、今回のようなAssemblyVersion 属性の重複なら、次の要素をcsprojに追加しましょう。
<PropertyGroup> <GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute> </PropertyGroup>
これでAssemblyInfo の生成自体をとめることなくビルドできるようになります。
obj に自動生成された ConsoleApp2.AssemblyInfo.cs
を見てみると、意図したとおり属性で指定したバージョンが埋め込まれていることがわかります。