如何检测哪种.NET语言正在调用我的代码

时间:2015-10-16 01:36:56

标签: .net reflection cil

我正在构建一个库,该库生成一个用户代理字符串,用于报告一些漂亮的数据,如操作系统版本和currently installed .NET Framework versions。我很好奇:

是否可以通过编程方式检测哪些语言正在调用我的库?或者,一旦将源语言编译成CIL,源语言是否完全不透明?

2 个答案:

答案 0 :(得分:5)

修改:我将其转换为small library,其中包含了一些启发式功能,可以轻松调用。

我提出了一种似乎适合我自己需要的启发式方法。

@ Don的回答,这些问题给了我一些提示:

<强>注意事项

  • 仅区分VB.NET和C#,而不区分任何其他CLR语言。如果没有足够的VB证据,请假设C#。
  • 它做了一个有根据的猜测,所以误报的可能性是&gt; 0
  • 一些提示基于编译器实现细节,可能会发生变化。
  • 这似乎也适用于Mono,但是YMMV。
  • 这是一种昂贵的反映,所以在现实生活中,你想把它包裹在Lazy<>或其他机制中,以确保它只被调用一次。
  • 正如@HABO所提到的,这可能是也可能不是非常有用的信息。我很想知道是否可以做到。
var lang = DetectAssemblyLanguage(Assembly.GetCallingAssembly());

public static string DetectAssemblyLanguage(Assembly assembly)
{
    var referencedAssemblies = assembly
        .GetReferencedAssemblies()
        .Select(x => x.Name);

    var types = assembly
        .GetTypes();

    // Biggest hint: almost all VB.NET projects have a
    // hidden reference to the Microsoft.VisualBasic assembly
    bool referenceToMSVB = referencedAssemblies.Contains("Microsoft.VisualBasic");

    // VB.NET projects also typically reference the special
    // (YourProject).My.My* types that VB generates
    bool areMyTypesPresent = types.Select(x => x.FullName).Where(x => x.Contains(".My.My")).Any();

    // If a VB.NET project uses any anonymous types,
    // the compiler names them like VB$AnonymousType_0`1
    bool generatedVbNames = types.Select(x => x.Name).Where(x => x.StartsWith("VB$")).Any();

    // If a C# project uses dynamic, it'll have a reference to Microsoft.CSharp
    bool referenceToMSCS = referencedAssemblies.Contains("Microsoft.CSharp");

    // If a C# project uses any anonymous types,
    // the compiler names them like <>f__AnonymousType0`1
    bool generatedCsNames = types.Select(x => x.Name).Where(x => x.StartsWith("<>")).Any();

    var evidenceForVb = new bool[] 
    {
        referenceToMSVB,
        myTypesPresent,
        vbGeneratedNames
    };

    var evidenceForCsharp = new bool[] {
        true, // freebie. ensures ties go to C#
        referenceToMSCS,
        csGeneratedNames
    };

    var scoreForVb = evidenceForVb.Count(x => x)
                     - evidenceForCsharp.Count(x => x);

    // In the case of a tie, C# is assumed
    return scoreForVb > 0
        ? "vb"
        : "cs";
}

答案 1 :(得分:3)

不幸的是,这是不可能的,正如您通过提及CIL所确定的那样。

我可以想到两种可能的解决方案:

  1. 但是,如果相应的.NET dll(调用代码程序集)的PDB文件可用,则可以检查此文件以确定使用的语言。然而,这是一个很大的“IF”,我会远离这样的解决方案。
  2. 检查调用程序集引用的程序集。有时(很少)可能会引用特定于语言的程序集。