SuperOli
SuperOli

Reputation: 1804

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.

Upvotes: 1

Views: 158

Answers (5)

Tergiver
Tergiver

Reputation: 14517

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();
    }
}

Upvotes: 1

CampaignWizard
CampaignWizard

Reputation: 838

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.

Upvotes: 0

Tim Lloyd
Tim Lloyd

Reputation: 38464

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 (i.e. URIs). In theory you could then use this information at runtime to request the appropriate source file from the web server.

Upvotes: 1

Femaref
Femaref

Reputation: 61467

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.

Upvotes: 0

Mike Caron
Mike Caron

Reputation: 14561

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?

Upvotes: 2

Related Questions