|
検索
タグ
ASP.NET
.NET
ASP.NET MVC
F#
Visual Studio
Azure
ASP.NET Core
ライトニングトーク
Plone
Selenium
AJAX
C#
jQuery
JavaScript
SQL Server
ADO.NET Entity Framework
WebMatrix
LINQ
EFCore
TypeScript
カテゴリ
最新の記事
最新のコメント
記事ランキング
最新のトラックバック
以前の記事
2026年 01月 2025年 12月 2025年 11月 2025年 10月 2025年 09月 2025年 08月 2025年 07月 2025年 06月 2025年 05月 2025年 04月 2025年 03月 2025年 02月 2024年 12月 2024年 11月 2024年 10月 2024年 09月 2024年 08月 2024年 04月 2024年 03月 2024年 02月 2024年 01月 2023年 12月 2023年 11月 2023年 10月 2023年 09月 2023年 08月 2023年 07月 2023年 06月 2023年 05月 2023年 04月 2023年 03月 2023年 02月 2023年 01月 2022年 12月 2022年 11月 2022年 10月 2022年 09月 2022年 08月 2022年 07月 2022年 06月 2022年 05月 2022年 04月 2022年 03月 2022年 02月 2022年 01月 2021年 12月 2021年 11月 2021年 10月 2021年 09月 2021年 08月 2021年 07月 2021年 06月 2021年 05月 2021年 04月 2021年 03月 2021年 02月 2021年 01月 2020年 12月 2020年 11月 2020年 10月 2020年 09月 2020年 08月 2020年 07月 2020年 06月 2020年 05月 2020年 04月 2020年 03月 2020年 02月 2020年 01月 2019年 12月 2019年 11月 2019年 10月 2019年 09月 2019年 08月 2019年 07月 2019年 06月 2019年 05月 2019年 04月 2019年 03月 2019年 02月 2019年 01月 2018年 12月 2018年 11月 2018年 10月 2018年 09月 2018年 08月 2018年 07月 2018年 06月 2018年 05月 2018年 04月 2018年 03月 2018年 02月 2018年 01月 2017年 12月 2017年 11月 2017年 10月 2017年 09月 2017年 08月 2017年 07月 2017年 06月 2017年 05月 2017年 04月 2017年 02月 2017年 01月 2016年 12月 2016年 11月 2016年 10月 2016年 09月 2016年 08月 2016年 07月 2016年 06月 2016年 05月 2016年 04月 2016年 03月 2016年 02月 2016年 01月 2015年 12月 2015年 11月 2015年 10月 2015年 09月 2015年 08月 2015年 07月 2015年 05月 2015年 04月 2015年 03月 2015年 02月 2015年 01月 2014年 12月 2014年 11月 2014年 10月 2014年 09月 2014年 08月 2014年 06月 2014年 04月 2014年 03月 2014年 02月 2014年 01月 2013年 12月 2013年 10月 2013年 09月 2013年 08月 2013年 07月 2013年 06月 2013年 05月 2013年 04月 2013年 03月 2013年 02月 2013年 01月 2012年 12月 2012年 11月 2012年 10月 2012年 09月 2012年 08月 2012年 07月 2012年 06月 2012年 05月 2012年 04月 2012年 03月 2012年 02月 2012年 01月 2011年 12月 2011年 11月 2011年 10月 2011年 09月 2011年 08月 2011年 07月 2011年 06月 2011年 05月 2011年 04月 2011年 03月 2011年 02月 2011年 01月 2010年 12月 2010年 11月 2010年 10月 2010年 09月 2010年 08月 2010年 07月 2010年 06月 2010年 05月 2010年 04月 2010年 03月 2010年 02月 2010年 01月 2009年 12月 2009年 10月 2009年 09月 2009年 07月 2009年 06月 2009年 05月 2009年 04月 2009年 03月 2009年 02月 2009年 01月 2008年 12月 2008年 11月 2008年 10月 2008年 09月 2008年 08月 2008年 07月 2008年 06月 2008年 05月 2008年 04月 2008年 03月 2008年 02月 2008年 01月 2007年 12月 2007年 11月 2007年 04月 2007年 03月 2007年 02月 2007年 01月 2006年 11月 2006年 10月 2006年 09月 2006年 08月 2006年 07月 |
2021年 04月 02日
C# でのプログラミングにおける話。 C# の ver.9、収録される .NET SDK のバージョンでいうと .NET SDK 5.0 からになるが、"ソースジェネレータ (Source Generators)" という機能が使えるようになった。 この "ソースジェネレータ" とは何かというと、いうなれば、C# コンパイラに対するある種の "アドイン" を、我々アプリケーションプログラマが実装・配付できる、という機能だ。 "ソースジェネレータ" = "(C#) ソースコードを生成するもの" という名のとおり、ビルド時に追加の C# ソースコードを動的に作成し、対象プロジェクトに付け加える、そういう "C# コンパイラに対するアドイン" プログラムを C# で作成できる、という仕組みになる。 下記の Qiita 記事などが参考になるかもしれない。 対象プロジェクトの既定の名前空間を知りたいさてこの C# ソースジェネレータは、いくつかの利用例があるのだが、そのひとつとして 「C# じゃないファイルから C# ソースコードを自動生成する」 というシナリオがある。 このシナリオにおいては、ソースジェネレータが生成する C# ソースコード中に記載の名前空間をどうしたものか、という問題につきあたる。 別のシナリオ、例えば 「partial な C# クラスに機能を付け加える (INotifyPropertyChanged の自動実装とか)」 といった場合は、対象の C# クラスの名前空間でソースコードを生成するしかないので、このような問題はとくには無い。 しかし前述の「C# じゃないファイルから C# ソースコードを自動生成する」というシナリオのときは、せめて対象プロジェクトの既定の名前空間を、ソースジェネレータ側で知る必要があると思う。 Compilation.GlobalNamespace というのを見つけたが...ということで、実際にソースジェネレータを実装しながら、対象プロジェクトの既定の名前空間を取得できるようなプロパティやメソッドが、ソースジェネレータに提供されるコンテキストオブジェクトにないか、インテリセンス (※自分は Windows OS 上で Visual Studio IDE を使って C# プログラミングをしている) で眺めてみた。 そうすると、 Compilation.GlobalNamespaceなどという、いかにもソレっぽいメンバーが見つかった。 そこで下記例のように、ソースジェネレータを実装して試してみた。 しかし残念ながら、この Compilation.GlobalNamespace プロパティ、どうひねくりまわしても、空文字しか返ってこない。 何か前提条件があるのかもしれないが、その点はよくわからず終いだった。 MSBuild プロパティを参照してみるそこで作戦を変更し、対象プロジェクトの MSBuild プロパティ値を取得してみることにした。 というのも、プロジェクトの既定の名前空間は、そのプロジェクトの "RootNamespace" という名前の MSBuild プロパティ値に設定されているからだ。 プロジェクト作成後に特に何も変更していなければ、この "RootNamespace" MSBuild プロパティ値はアセンブリの出力名と同じに設定されている。 明示的に指定する場合は、当該プロジェクトの .csproj ファイル中に、以下のように MSBuild プロパティ値の記載となって現れる (下記例)。 さて、まずは GitHub 上で公開されている "Source Generators Cookbook" というドキュメント (下記) を参照してみる。 すると、"Consume MSBuild properties and metadata" というセクションに、そのものズバリの手順が載っていた。 まず、ソースジェネレータ側では、なんでもかんでも、対象プロジェクトの MSBuild プロパティを取得できるわけではないらしい。 対象プロジェクト内で明示的に指定された MSBuild プロパティ値のみが取得できるようだ。 具体的には、対象プロジェクト内の "<ItemGroup>" メンバとして、"<CompilerVisibleProperty>" 項目を記載し、その "Include" 属性値に、ソースジェネレータからの参照を行ないたい MSBuild プロパティの名前を記載する。 今回のお題である、既定の名前空間は、MSBuild プロパティ "RootNamespace" に設定されているので、これをソースジェネレータから参照できるよう、対象プロジェクトに以下のようなノードを追加する。 こうしておくことで、ソースジェネレータ側では、以下のような実装にて、対象プロジェクトの MSBuild プロパティ、すなわち今回の例だと、既定の名前空間を取得することができた。 なお、取得したい MSBuild プロパティ名をそのまま "AnalyzerConfigOptions.GlobalOptions.TryGetValue()" に渡すのではなく、"build_property.~" という前置詞を付ける必要がある。 名前空間に限らず、任意の MSBuild プロパティを取得可能今回のお題では、ソースジェネレータの対象プロジェクトの、既定の名前空間をいかに取得するか、ということであった。 しかしこの方法は、既定の名前空間の取得に限らず、任意の MSBuild プロパティをソースジェネレータから取得可能であることを意味する。 対象プロジェクト側 .csproj ファイル内で、"<CompilerVisibleProperty Include="MSBuild プロパティ名" />" という ItemGroup 項目を記載して明示的に参照可能にする必要はあるものの、この方法で MSBuild プロパティを参照すれば、他にも以下のような情報を入手可能だ。
もちろん、上記はあくまで例なので、ソースジェネレータコンテキストの "Compilation" プロパティを参照すればわかるものもあるかもしれない (※自分は詳細は未確認)。 しかしとにかく、対象プロジェクトの MSBuild プロパティを取得できることで、ソースジェネレータの実装の幅が広がることだろう。 NuGet パッケージにして再配布するならなお、最終的には、開発したソースジェネレータは NuGet パッケージ化して配付する需要が発生することが多いと思う。 そうしたときには、その NuGet パッケージ内には、ソースジェネレータのビルド後の .dll のみならず、前述の "<CompilerVisibleProperty Include="MSBuild プロパティ名" />" の記載を含む .props ファイルも同梱しておくのがよいかと思う。 というのも、利用者に 「この NuGet パッケージを使うときは、"<CompilerVisibleProperty Include="MSBuild プロパティ名" />" を .csproj に記載してください」 とお願いするのはどうかと思うからだ。 このブログ記事では詳細は割愛しここまでとするが、このように、対象プロジェクト内の MSBuild プロパティ値を使用するソースジェネレータも、NuGet パッケージ化して配付できるよ、ということだ。 以上。
by developer-adjust
| 2021-04-02 11:34
| .NET
|
ファン申請 |
||