Castleライブラリから学んだC#で動的に型情報を生成する方法
はじめに
前回記事の続きです。
https://qiita.com/mngreen/items/f49b7c6b305f86d63e6d
前回記事より、DynamicProxyでは動的に型を生成していることが分かりました。
本記事ではその動的に型を生成する処理について、見ていきたいと思います。
動的に型を生成する
実際に型を生成しているメソッドというのは、以下のリンク先のBaseInterfaceProxyGenerator.GenerateTypeメソッドの処理になります。
https://github.com/castleproject/Core/blob/c6d7a165ac3050ebfc70debabe52ee6624a97bdf/src/Castle.Core/DynamicProxy/Generators/BaseInterfaceProxyGenerator.cs#L87
上記の処理の中で、ClassEmitterクラスのBuildTypeメソッドが最終的に型情報を生成しています。
まずはClassEmitterのBuildTypeメソッドを探しにいきますが、存在しないためベースクラスであるAbstractTypeEmitterを見にいきます。
その中には、確かにBuildTypeメソッドがありました。
BuildTypeメソッドの中身を見ていくと、最終的にはTypeBuilder.CreateTypeInfoメソッドが呼び出されています。
TypeBuilderクラスのドキュメントは以下から参照できます。このような型があること自体を知らなかったので、勉強になりました。
https://learn.microsoft.com/ja-jp/dotnet/api/system.reflection.emit.typebuilder?view=net-7.0
正直、ドキュメントの例を見ても直感的にとらえられていないのですが、大体以下の手順を踏んでいるようです。
- アセンブリを生成するためのビルダを生成する。
- 1.のビルダからモジュールを生成するためのビルダを生成する。
- アセンブリとモジュールの違いはマニフェストの有無ぐらいのようです。https://atmarkit.itmedia.co.jp/fdotnet/technology/framework01/framework01_03.html
- 2.のビルダに型情報を定義する
- 3.の型情報の中にコンストラクタやフィールド、プロパティ、メソッドなどの詳細を定義
- 4.の型情報をビルドして型を生成。あとはCreateInstanceをすることでインスタンス化可能
比較的単純なこの例ですら複雑さを感じるのに、DynamicProxyではどのように上手く取り扱っているのでしょうか?
おわりに
CastleライブラリからTypeBuilderクラスの存在を知り、サンプルを自分なりの理解で書き下してみました。
独力で作り上げようとしたらこのような複雑な処理を書かなければいけないところを、うまく抽象化してくれていて非常に助かりますね。
これで少しだけ仕組みが分かってきたので、さらにもう少し読み込んでいこうと思います。