dll から見たときに、実行中のプログラムが何言語(C# or VB.NET)で書かれているかを判断する
という判定で悩んでいたんですが、一応対策が浮かんだので残しておきます。
目次
件名がイミフ?
何がしたかったのかいまいちなので具体例を出しますと、VB.NET で書いた exeVB, C# で書いた exeCS, C# で書いた dllCS があったとして、exeVB も exeCS も dllCS を参照追加して使っているとします。ターゲットフレームワークは 3 つとも同じバージョンです。
この時 exeVB から dllCS(のメソッド)を呼び出した場合は、dllCS 側では "VB.NET から呼ばれた" と自動判断したい、exeCS から dllCS(のメソッド)を呼び出した場合は、dllCS 側では "C# から呼ばれた" と自動判断したい。で、リフレクションで取ってきた型データを、言語別に表示したい(ex. C# -> List
一応自分なりにありそうだと思った Assembly 周りと Environment 周りを探してみたのですが、開発言語を取得できる命令は見つけられませんでした。皆様ならどうやって判断しますか?
答え(自動生成クラスの有無で判断する)
調べた結果、ロード中の全アセンブリの中にあるクラスから、自動生成されるクラスの "プロジェクト名前空間.My.MySettings" があるか無いかで判断できることを思いつきました。
これは、VB.NET 言語の機能で、クラスが分からなくてもショートカットで探し出せる My 機能("My." とタイピングしてそれらしいキーワードをたどっていく)があるのですが、VB.NET のプロジェクトの場合、このクラスが自動生成されます。dllCS 側で、これを調べれば実現できそうです!
ただ、Console, WindowsForms, WPF, Web, ... と全てに当てはまるかは分からないです。確か VS2003 の時は無かったような。
サンプルコード
以下サンプルです。Type.FullName
の有無チェックはもしかしたら不要かもです^^;
bool CalledVBNETSource() { var asms = AppDomain.CurrentDomain.GetAssemblies(); var classTypes = asms .SelectMany(x => x.GetTypes()) .Where(y => y.IsClass) .Select(z => string.IsNullOrEmpty(z.FullName) ? z.Name : z.FullName); return classTypes.Any(x => x.EndsWith(".My.MySettings")); }
Function CalledVBNETSource() As Boolean Dim asms() As Assembly = AppDomain.CurrentDomain.GetAssemblies() Dim classTypes As IEnumerable(Of String) = asms. SelectMany(Function(x) x.GetTypes()). Where(Function(y) y.IsClass). Select(Function(z) If(String.IsNullOrEmpty(z.FullName), z.Name, z.FullName)) Return classTypes.Any(Function(x) x.EndsWith(".My.MySettings")) End Function
というか
dllCS のメソッド呼び出し時に、言語選択の列挙体を渡してもらうように作れば確実なんですよね~。でもそれが無くても自動的に判断できるのが、一段階上のプログラムっていうか~。こだわりっていうか~。どうでもいいことなのかもしれないけど、なかなか妥協できないっていうね・・・。