简体   繁体   中英

Is it possible to retrieve the file containing a class at runtime?

I would like to know if it's possible to retrieve the .cs file that contains a certain class at runtime.

Ex. I have the "Type" that represents my class (public class Foo) and from that, I would like to retrieve the path to its parent file ("c:\\foo.cs").

Thanks

Edit: The purpose of this would be to show some classes' name to the user in a ListView (populated programmatically) for example and when he double clicks on one of the ListViewItem, it opens the .cs file that contains the class in question.

If you bundle your source code, then sure. In which case, you already know where it is.

However, source code is NOT included by default with a compiled program, and as such you cannot retrieve it at run time.

Perhaps if you expand on what you're trying to do, we may be able to help?

Yes you can using Source Server although you would have to distribute indexed symbol files (PDBs) with your program.

Setting up a Source Server implementation is non-trivial, to say the least.

The basics of the mechanism are that all source-code for your application is published to a web server, and your PDB files are re-written with information that ties type information to locations of the source code (ie URIs). In theory you could then use this information at runtime to request the appropriate source file from the web server.

It is possible, but there is no 'magic' way that I know of. You'll have to add a method to every type you want to support this. Also it will only work if the .pdb file is available. _GetSourceFileName returns null without it.

using System;
using System.Reflection;

class Program
{
    static void Main(string[] args)
    {
        DumpFilenameForType(typeof(A));
        DumpFilenameForType(typeof(B));

        if (System.Diagnostics.Debugger.IsAttached)
        {
            System.Console.Write("Press any key to continue . . . ");
            System.Console.ReadKey();
        }
    }

    static void DumpFilenameForType(Type t)
    {
        MethodInfo mi = t.GetMethod("_GetSourceFileName", BindingFlags.Static | BindingFlags.NonPublic);
        if (mi != null)
            Console.WriteLine("Type '{0}' is located in '{1}'", t.FullName, mi.Invoke(null, null));
        else
            Console.WriteLine("Type '{0}' does not provide method _GetSourceFileName", t.FullName);
    }
}

// Some other file

public class A
{
    static string _GetSourceFileName()
    {
        return new System.Diagnostics.StackTrace(true).GetFrame(0).GetFileName();
    }
}

// Yet another other file

public class B
{
    static string _GetSourceFileName()
    {
        return new System.Diagnostics.StackTrace(true).GetFrame(0).GetFileName();
    }
}

As there is no reference to the sourcecode in the assembly itself, this would only work if you have access to the debugging databases (.pdb) as well. Even then, it still will be very hard to get to this information.

When you compile your C# program, the source code gets translated into CIL and placed inside an assembly. The original raw source file is not copied over, so the Type object can not retrieve it.

In order to access the source code, you will need to include it in your build process and load the file without using the Type object.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM