如何检测哪种.NET语言正在调用我的代码 [英] How to detect which .NET language is calling my code
问题描述
我正在构建一个生成用户代理字符串的库,该字符串报告一些漂亮的数据,例如OS版本和当前安装的.NET Framework版本。我很好奇:
I'm building a library that generates a user-agent string that reports some nifty data like OS version and currently installed .NET Framework versions. I'm curious:
是否可以通过编程方式检测到正在调用我的图书馆的语言?还是将源语言编译为CIL后完全不透明?
Is it possible to detect programmatically which language is calling my library? Or is the source language completely opaque once it's compiled into CIL?
推荐答案
编辑:放入小型库中,该库封装了一些启发式方法,并且易于调用。
Edit: I turned this into a small library that encapsulates a few heuristics and makes it easy to call.
我想出了一种启发式方法,似乎可以很好地满足我自己的需求。
I came up with a heuristic that seems to work well enough for my own needs.
@Don的回答,这些问题使给我一些提示:
@Don's answer and these questions gave me some hints:
- Decompiled DLL - Clues to help tell whether it was C# or VB.NET?
- Decompiling VB.Net assembly produces code with invalid member variable names; names starting with $STATIC$
注意事项:
- 仅区分VB.NET和C#,不区分其他CLR语言。假设C#没有足够的VB证据。
- 这是有根据的猜测,因此误报的可能性大于0。
- 某些提示是基于编译器实现的详细信息,可能会更改。
- 这似乎也适用于Mono,但是YMMV。
- 昂贵的反射,因此在现实生活中,您希望将其包装在
Lazy<>
或其他某种机制中,以确保仅调用一次。 - 如@HABO所述,这可能是非常有用的信息,也可能不是。我主要是想知道是否可以这样做。
- Only differentiates between VB.NET and C#, not any other CLR languages. Assumes C# if it doesn't have enough evidence of VB.
- It's making an educated guess, so the chance of false positives is > 0.
- Some of the hints are based on compiler implementation details, which could change.
- This seems to work on Mono too, but YMMV.
- It's expensive reflection, so in real life you'd want to wrap it in a
Lazy<>
or some other mechanism to ensure it's only called once. - As @HABO mentioned, this may or may not be very useful information. I was mostly curious to see if it could be done.
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";
}
这篇关于如何检测哪种.NET语言正在调用我的代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!