2010-10-28 52 views
5

给定.NET中的Type对象,我可以获取源代码文件名吗?我知道这只会在调试版本中可用,这很好,我也知道我可以使用StackTrace对象来获取调用堆栈中特定帧的文件名,但这不是我想要的。从调试版本中的类型获取文件的源代码文件名

但是我可以得到给定System.Type的源代码文件名吗?

+0

[如何获取源文件名和类型成员的行号?](http://stackoverflow.com/questions/126094/how-to-get-the-source-file-name线型号的会员) – 2010-10-28 07:29:06

+0

你为什么要这样做?我能想到的大部分原因都可以通过像Symbol/Source服务器这样的工具来解决...... – 2010-10-28 22:16:42

回答

3

考虑到至少C#支持部分类声明(例如,public partial class Foo在两个源代码文件中),“给定System.Type的源代码文件名”是什么意思?如果类型声明分散在同一个程序集内的多个源代码文件中,那么在声明开始的源代码中没有单一的点。

@Darin Dimitrov:这看起来不像“如何获取源文件名和类型成员的行号?”的副本。对我来说,因为这是一个类型成员,而这个问题是关于类型。我用这样的代码

+0

我们在我的公司大规模地重构名称空间和类似的东西,我想编写一个单元测试来检查命名空间是否对应到文件位置。我们现在实际上已经完成了,所以我不再需要它了,但问题仍然存在,必须有某种方法可以访问pdb并获取此信息?至于部分类,那么我们应该能够获得这两个文件名。 – 2010-11-08 07:27:10

+0

@Michael它会是'string []':-D – 2013-07-17 12:22:16

+0

@Simon_Weaver嗯,但是,OP要求为给定System.Type输入*** ***源代码文件名:-) – 2013-07-17 12:32:17

3

摆脱方法正在运行的源文件和行号:

//must use the override with the single boolean parameter, set to true, to return additional file and line info 

System.Diagnostics.StackFrame stackFrame = (new System.Diagnostics.StackTrace(true)).GetFrames().ToList().First(); 

//Careful: GetFileName can return null even though true was specified in the StackTrace above. This may be related to the OS on which this is running??? 

string fileName = stackFrame.GetFileName(); 
string process = stackFrame.GetMethod().Name + " (" + (fileName == null ? "" : fileName + " ") + fileLineNumber + ")"; 
3

我遇到了类似的问题。我只需要使用类的类型和方法名称来找到特定方法的文件名和行号。我在一个旧的单声道.net版本(统一4.6)。我使用了库cecil,它提供了一些帮助来分析您的pbd(或mdb for mono)并分析调试符号。 https://github.com/jbevain/cecil/wiki

对于给定的类型和方法:

System.Type myType = typeof(MyFancyClass); 
string methodName = "DoAwesomeStuff"; 

我发现这个解决方案:

Mono.Cecil.ReaderParameters readerParameters = new Mono.Cecil.ReaderParameters { ReadSymbols = true }; 
Mono.Cecil.AssemblyDefinition assemblyDefinition = Mono.Cecil.AssemblyDefinition.ReadAssembly(string.Format("Library\\ScriptAssemblies\\{0}.dll", assemblyName), readerParameters); 

string fileName = string.Empty; 
int lineNumber = -1; 

Mono.Cecil.TypeDefinition typeDefinition = assemblyDefinition.MainModule.GetType(myType.FullName); 
for (int index = 0; index < typeDefinition.Methods.Count; index++) 
{ 
    Mono.Cecil.MethodDefinition methodDefinition = typeDefinition.Methods[index]; 
    if (methodDefinition.Name == methodName) 
    { 
     Mono.Cecil.Cil.MethodBody methodBody = methodDefinition.Body; 
     if (methodBody.Instructions.Count > 0) 
     { 
      Mono.Cecil.Cil.SequencePoint sequencePoint = methodBody.Instructions[0].SequencePoint; 
      fileName = sequencePoint.Document.Url; 
      lineNumber = sequencePoint.StartLine; 
     } 
    } 
} 

我知道这是一个有点晚:)但我希望这会帮助别人!