Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Roslyn とその活用法

neno
September 24, 2022

Roslyn とその活用法

.NET ラボ 2022/09/24 での発表資料

GitHub
- Tapper
- TypedSignalR.Client
- TypedSignalR.Client.TypeScript
Twitter
Blog
neno.dev

neno

September 24, 2022
Tweet

More Decks by neno

Other Decks in Technology

Transcript

  1. 自己紹介 1 • 所属: NTTコミュニケーションズ イノベーションセンター • 趣味: C#, OSS,

    ドール, 一眼(α7 IV) 何縫ねの。 nenoNaninu nenoMake ブログ https://blog.neno.dev その他 https://neno.dev
  2. Roslyn 3 • .NET Compiler Platform • Compiler as a

    Service • C#で書かれた、C#コンパイラ • Compiler API が生えている。 https://github.com/dotnet/roslyn Roslyn C# の観点からみれば
  3. • Source Generator • Analyzer • Console App Roslyn 17

    Compiler APIを通して出来る事。
  4. • Source Generator • Analyzer • Console App Roslyn 19

    Compiler APIを通して出来る事。 Roslyn 組み込みの機能
  5. • Source Generator • Analyzer • Console App Roslyn 20

    Compiler APIを通して出来る事。 Roslyn 組み込みの機能 Roslyn を普通の ライブラリとして使用
  6. • Source Generator • Analyzer • Console App Roslyn 21

    Compiler APIを通して出来る事。 Roslyn 組み込みの機能 Roslyn を普通の ライブラリとして使用 活用例(OSS)と共に紹介
  7. • Source Generator • Analyzer • Console App Roslyn 22

    Compiler APIを通して出来る事。 Roslyn 組み込みの機能 Roslyn を普通の ライブラリとして使用 活用例(OSS)と共に紹介
  8. Roslyn : Console App 25 Server (C#) Client (TypeScript) JSON

    https://blog.neno.dev/entry/2022/03/31/213837
  9. Roslyn : Console App 26 Server (C#) Client (TypeScript) JSON

    https://blog.neno.dev/entry/2022/03/31/213837
  10. Roslyn : Console App 27 Server (C#) Client (TypeScript) JSON

    https://blog.neno.dev/entry/2022/03/31/213837 両方手書き?
  11. Roslyn : Console App 28 Server (C#) Client (TypeScript) JSON

    Server側を変更したらClient側は コンパイルエラー吐いて欲しい https://blog.neno.dev/entry/2022/03/31/213837 両方手書き?
  12. Roslyn : Console App 29 JSON 両方手書き? Server (C#) Client

    (TypeScript) https://blog.neno.dev/entry/2022/03/31/213837 Server側を変更したらClient側は コンパイルエラー吐いて欲しい
  13. Roslyn : Console App 30 JSON 両方手書き? Client (TypeScript) Server

    (C#) https://blog.neno.dev/entry/2022/03/31/213837 Server側を変更したらClient側は コンパイルエラー吐いて欲しい
  14. Roslyn : Console App 35 • C#の型定義からTypeScriptの型定義を 生成するConsole App •

    Roslynで意味解析まで行い、対象の型の 名前、メンバの型/名前等を 読み取ってTypeScriptコードを生成。 • シリアライザによって生成する型を 適切に調整 $ tapper --project path/to/Xxx.csproj --output generated https://github.com/nenoNaninu/Tapper Tapper
  15. Roslyn : Console App 36 • C#の型定義からTypeScriptの型定義を 生成するConsole App •

    Roslynで意味解析まで行い、対象の型の 名前、メンバの型/名前等を 読み取ってTypeScriptコードを生成。 • シリアライザによって生成する型を 適切に調整 $ tapper --project path/to/Xxx.csproj --output generated https://github.com/nenoNaninu/Tapper Tapper Attributeをアノテーションするだけ
  16. Roslyn : Console App 37 • C#の型定義からTypeScriptの型定義を 生成するConsole App •

    Roslynで意味解析まで行い、対象の型の 名前、メンバの型/名前等を 読み取ってTypeScriptコードを生成。 • シリアライザによって生成する型を 適切に調整 $ tapper --project path/to/Xxx.csproj --output generated https://github.com/nenoNaninu/Tapper Tapper Attributeをアノテーションするだけ JSON/MsgPack 対応
  17. Roslyn : Console App 38 • C#の型定義からTypeScriptの型定義を 生成するConsole App •

    Roslynで意味解析まで行い、対象の型の 名前、メンバの型/名前等を 読み取ってTypeScriptコードを生成。 • シリアライザによって生成する型を 適切に調整 $ tapper --project path/to/Xxx.csproj --output generated https://github.com/nenoNaninu/Tapper Tapper Attributeをアノテーションするだけ 1コマンド! JSON/MsgPack 対応
  18. Roslyn : Console App 41 詳細な JSDoc どの C# 型由来か一目瞭然

    Tapper TypeScript での number が int か float かで迷わない!
  19. Roslyn : Console App 44 • ユーザー定義型がネストしたら? Tapper https://github.com/nenoNaninu/Tapper Attributeがアノテーション

    されてる型の中で ユーザ定義型が使われている 中で使われる型にも Attributeを アノテーションする 必要がある
  20. Roslyn : Console App 45 • ユーザー定義型がネストしたら? Tapper https://github.com/nenoNaninu/Tapper Attributeがアノテーション

    されてる型の中で ユーザ定義型が使われている 中で使われる型にも Attributeを アノテーションする 必要がある Attributeなので コンパイル時に 制約出来ない。 →ランタイムエラー?
  21. • Source Generator • Analyzer • Console App Roslyn 46

    Compiler APIを通して出来る事。
  22. • Source Generator • Analyzer • Console App Roslyn 47

    Compiler APIを通して出来る事。
  23. • Source Generator • Analyzer • Console App Roslyn 52

    Compiler APIを通して出来る事。
  24. • Source Generator • Analyzer • Console App Roslyn 53

    Compiler APIを通して出来る事。
  25. Roslyn: Source Generator 56 字句解析 構文解析 意味解析 コード生成 Source Generator

    とは Compilation を取得 構文木/意味モデルなどが 全て含まれている
  26. Roslyn: Source Generator 57 字句解析 構文解析 意味解析 コード生成 Source Generator

    とは https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview Compilation を取得 構文木/意味モデルなどが 全て含まれている
  27. Roslyn: Source Generator 58 字句解析 構文解析 意味解析 コード生成 Source Generator

    とは Compilation を取得 https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview 動的コード生成 IL Generator Expression Tree (Reflection) 構文木/意味モデルなどが 全て含まれている
  28. Roslyn: Source Generator 59 字句解析 構文解析 意味解析 コード生成 Source Generator

    とは Compilation を取得 https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview 構文木/意味モデルなどが 全て含まれている 8割くらいは Source Generator で代替 動的コード生成 IL Generator Expression Tree (Reflection)
  29. Roslyn: Source Generator 60 • interface ISourceGenerator • 全ソースコードを探索 →

    必要箇所を収集 → コード生成 .NET 5 .NET 6 • interface IIncrementalGenerator • ソースコードの変更を検知 → 変更箇所が必要箇所か検査 → 必要箇所だった場合のみ コード生成のロジックが発火
  30. Roslyn: Source Generator 61 • interface ISourceGenerator • 全ソースコードを探索 →

    必要箇所を収集 → コード生成 .NET 5 .NET 6 • interface IIncrementalGenerator • ソースコードの変更を検知 → 変更箇所が必要箇所か検査 → 必要箇所だった場合のみ コード生成のロジックが発火 IDE で一文字変更毎に 全ソース探索/コード生成が実行され 開発体験が厳しかった
  31. Roslyn: Source Generator 62 • interface ISourceGenerator • 全ソースコードを探索 →

    必要箇所を収集 → コード生成 .NET 5 .NET 6 • interface IIncrementalGenerator • ソースコードの変更を検知 → 変更箇所が必要箇所か検査 → 必要箇所だった場合のみ コード生成のロジックが発火 IDE で一文字変更毎に 全ソース探索/コード生成が実行され 開発体験が厳しかった IDE フレンドリー! 書き心地も向上!
  32. Roslyn: Source Generator 66 • 双方向のリアルタイム通信機能を提供する RPC ライブラリ • WebSocket

    が繋がらなくても大丈夫! • .NET Core移行時に実装を大幅に改良、現在も機能追加がされ続けている。 • 認証認可が .NET Core 3.1 で組み込まれたり。.NET 7 でも新機能が予定されてる。 • ASP.NET Core 組み込み。 • リポジトリ的にも ASP.NET Core の中。 • Blazor Server とかでも使われている。 SignalR とは https://github.com/dotnet/aspnetcore/tree/main/src/SignalR
  33. Roslyn: Source Generator 67 • Hubの method をinvokeする際 / Client

    の method を登録をする際、 • ①method 指定が文字列で辛い。 • ②引数/返り値の型を手動で与える必要があり辛い。 SignalR の問題点 https://github.com/dotnet/aspnetcore/tree/main/src/SignalR
  34. Roslyn: Source Generator 68 SignalR の問題点 https://github.com/dotnet/aspnetcore/tree/main/src/SignalR タイポ怖い 変更に追従させるの大変 •

    Hubの method をinvokeする際 / Client の method を登録をする際、 • ①method 指定が文字列で辛い。 • ②引数/返り値の型を手動で与える必要があり辛い。
  35. Roslyn: Source Generator 69 SignalR の問題点 https://github.com/dotnet/aspnetcore/tree/main/src/SignalR タイポ怖い 変更に追従させるの大変 Source

    Generator を活用して解決! • Hubの method をinvokeする際 / Client の method を登録をする際、 • ①method 指定が文字列で辛い。 • ②引数/返り値の型を手動で与える必要があり辛い。
  36. Roslyn: Source Generator 71 TypedSignalR.Client server 側は interface で 強く型付け出来る。

    一方 client 側は… https://github.com/nenoNaninu/TypedSignalR.Client
  37. Roslyn: Source Generator 75 TypedSignalR.Client Before After https://github.com/nenoNaninu/TypedSignalR.Client 型引数に渡された interface

    を 実装した class を内部で生成 server 側は interface で 強く型付け出来る。 一方 client 側は…
  38. Roslyn: Source Generator 76 TypedSignalR.Client Before After 型引数に渡された interface で

    定義されている全methodを connection に bind する コードを内部で生成 https://github.com/nenoNaninu/TypedSignalR.Client 型引数に渡された interface を 実装した class を内部で生成 server 側は interface で 強く型付け出来る。 一方 client 側は…
  39. Roslyn: Source Generator 77 • 仕様に従ってない場合 • 型引数に interface 以外を渡している

    • interfaceに property, 不正な返り値/引数のmethod 等 TypedSignalR.Client コンパイルエラー! 詳細なエラーメッセージ ライブラリの仕様を知らなくても正しく使える! さらば ランタイムエラー!
  40. Roslyn: Source Generator 81 事前に必要なコードを一度だけ生成 TypedSignalR.Client の場合は 拡張メソッドなど 変更箇所に対する検証/整形などの パイプラインを

    Rx ライクに記述 https://github.com/nenoNaninu/TypedSignalR.Client/blob/v3.1.1/src/TypedSignalR.Client/SourceGenerator.cs 構築したパイプラインを使って コードを生成/登録
  41. Roslyn: Console App + Code Analyzer 84 • C#のinterfaceを解析 →

    TypeScriptで強く型付けされた SignalR clientを提供 TypedSignalR.Client.TypeScript $ dotnet tsrts --project path/to/Xxx.csproj --output generated https://github.com/nenoNaninu/TypedSignalR.Client.TypeScript
  42. Roslyn: Console App + Code Analyzer 85 • C#のinterfaceを解析 →

    TypeScriptで強く型付けされた SignalR clientを提供 TypedSignalR.Client.TypeScript $ dotnet tsrts --project path/to/Xxx.csproj --output generated https://github.com/nenoNaninu/TypedSignalR.Client.TypeScript Attribute を アノテーションするだけ Attribute を アノテーションするだけ
  43. Roslyn: Console App + Code Analyzer 86 • C#のinterfaceを解析 →

    TypeScriptで強く型付けされた SignalR clientを提供 TypedSignalR.Client.TypeScript $ dotnet tsrts --project path/to/Xxx.csproj --output generated https://github.com/nenoNaninu/TypedSignalR.Client.TypeScript Attribute を アノテーションするだけ Attribute を アノテーションするだけ 1 コマンド!
  44. Roslyn: Console App + Code Analyzer 90 TypedSignalR.Client.TypeScript Before After

    型指定さえすれば テンプレートはエディタ が吐き出してくれる
  45. Roslyn: Console App + Code Analyzer 91 TypedSignalR.Client.TypeScript Before After

    型指定さえすれば テンプレートはエディタ が吐き出してくれる 文字列 つかってるじゃん?
  46. Roslyn: Console App + Code Analyzer 93 TypedSignalR.Client.TypeScript Before After

    文字列 つかってるじゃん? string literal type で overload してるので大丈夫。 Intellisense もバッチリ
  47. Roslyn: Console App + Code Analyzer 94 メソッド定義に Tapper の

    Attribute が付いてない型を 使っていた場合に警告 https://github.com/nenoNaninu/TypedSignalR.Client.TypeScript#analyzer TypedSignalR.Client.TypeScript は Tapper 内蔵してこれを解決 SignalR の hub/receiver method で ユーザ定義型を使いたい
  48. まとめ 95 • Source Generator • C# コードを解析してC# コードを生成!以下の要望をストレートに解決! •

    動的コード生成しないと厳しいな~ • ボイラーコード大量に発生するな~ • Analyzer • 型で制約できない事はAnalyzerで制約!リアルタイムに発見! • Tapperのように外部ツール都合のAttributeの使い方を矯正 • このAPI使うな!この返り値を捨てるな!とか、使い道はいろいろ。 • 頑張れば code fix も • Console App • C# コードと連携する他言語(TypeScript等)をより快適に! • ぶっちゃけなんでもできます!やりたい放題! Roslyn を使う事で C# コードを入力として、アレコレ出来る!