我正在构建一个库,该库生成一个用户代理字符串,用于报告一些漂亮的数据,如操作系统版本和currently installed .NET Framework versions。我很好奇:
是否可以通过编程方式检测哪些语言正在调用我的库?或者,一旦将源语言编译成CIL,源语言是否完全不透明?
答案 0 :(得分:5)
修改:我将其转换为small library,其中包含了一些启发式功能,可以轻松调用。
我提出了一种似乎适合我自己需要的启发式方法。
@ Don的回答,这些问题给了我一些提示:
<强>注意事项强>:
Lazy<>
或其他机制中,以确保它只被调用一次。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所确定的那样。
我可以想到两种可能的解决方案: