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, VB.NET -> List(Of String), 等)というわけです。

一応自分なりにありそうだと思った 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 のメソッド呼び出し時に、言語選択の列挙体を渡してもらうように作れば確実なんですよね~。でもそれが無くても自動的に判断できるのが、一段階上のプログラムっていうか~。こだわりっていうか~。どうでもいいことなのかもしれないけど、なかなか妥協できないっていうね・・・。