Archive for 8月 2013
今更ながらBuild 2013の
昨日のcodeseek/C#UG勉強会向けに書いたもの。
メモ書き程度で済まそうと思っていたものの、そこそこ形にしちゃったのでスライド公開。
本来は、ちゃんとBuild 2013直後(=2か月前)に作って出した方がよかったんだろうなぁという内容ですが、今更ながら。
C# → C# コード生成
最近の趣味コード。
装飾なしのC#クラスから、ちゃんとした機能付きのC#クラスを作るコード。
仕事で似たようなコードを作って実用しているものの、結構ごてごてしててどうしたものかと悩んでいたところ、もっとシンプルにやる方法を思いついたので実装中。
というか、結構よくコード生成やる。要は、何回か同じの作ってるうちにこなれてきてしまった感じ。
どうやって
- 生成元:
- 単一名前空間に生成元になるクラスだけを書いた dll
- 生成に使ってるもの
- リフレクションで型情報を取ってきて、それを元に新しい型を作る
- T4テンプレートを使ってコード生成
- Microsoft.Build.dll 使って .csproj ファイルを直書き換えして、生成した .cs ファイルをプロジェクトに登録
どういうものを
- インターフェイスは get オンリー
- mutable クラス:
- get/set あり
- コレクションは普通の配列を使う
- immutable クラス:
- get のみ(コンストラクターでの初期化のみ)
- コレクションは Bcl.Immutable の ImmutableArray を使う
- observable クラス:
- get/set あり
- INotifyPropertyChanged を実装
- コレクションは ObservableCollection を使う
- JSON クラス:
- プロパティ内で Json.NET の JObject を書き換え
- ToString で JSON 化
- (リフレクションを使えない環境用に、動的な処理なしで JSON 化するため)
- どれも同じインターフェイスを実装
- インターフェイスを引数に取るコンストラクターを使って、相互変換とかディープ クローン可能
その他、所感
C# とか Java は型システムが基礎的過ぎて、定型コードが多くなりがちとか言われるものの。
かといって、コンパイラーの内部でいろいろと生成されたいかというと微妙だし、実行時に動的コード書き替えとかして処理をはさむのはマジで勘弁してほしいし。
ということで、ツール上で静的にコード生成したいわけで、それをやってるだけ。
生成元になる型情報は、せっかくしっかりした型システムを持ってるわけだから、C# 自身を使いたく。C# → C# コード生成。
ただ、今の作りだと「型定義側を書き替えるたびに、型定義プロジェクトのビルド後、コード生成プログラムを手動で実行」っていう手順が挟まるんで、扱いづらいというか、完全に黒魔術。ここが自動化というか、Visual Studio に組み込めたりするといいんだけども。
状況
実は、新しく作ってる方はまだインターフェイスと mutable しか生成できてないし、enum に対応してなかったりとか、まだ作り始めたところ(仕事でやってるごてごてしてる方では上記要件満たせてる)。
ある程度形になったところで GitHub 辺りにでも置こうかな。
あと、JSON じゃなくてもっとコンパクトなバイナリ形式シリアライズとかもやりたいのと、 .NET 3.5 用(主に Unity 向け。オプション引数/既定値と、ジェネリックの変性、Caller Info を抜く)作る必要あり。