tags:

views:

135

answers:

4

I'm trying to find all member fields (but not local variables) of a particular type (e.g. Widget) across a large codebase.

I'm using VS2005 but don't mind non-vs solutions.

If I were using C++ I could limit my search to header files, but that doesn't work in c#

I could search for "Widget m_" but that risks missing fields that haven't been named correctly.

Any other ideas?


Further info:

I have a definitive list of Widgets in my WidgetManager. Any other class can have a pointer to a Widget. If I delete a Widget from my WidgetManager, I want all the other pointers to that widget (wherever they might be in the solution) to be set to null.

A "destroyed" event is raised when a Widget is removed from my WidgetManager. I was thinking of catching that event in all the classes that store references to Widgets, and setting their references to null when Widgets were deleted. The point of my original question is to verify that I've found all the references.

If anyone can think of a Better Way then let me know.

A: 

Is the codebase one solution? If so, go to that type, right click the type's name and select "Find all references".

Andrew Hare
That will include local variables which the OP does not want.
JaredPar
+2  A: 

Use reflection to inspect the compiled dlls. Iterate through all types and find all properties that reference the type..

EDIT

Here's a sample that finds all properties exposing a string in the current app domain.

public static void Main(string[] args)
{
    printAllPublicPropertiesInCurrentAppDomain(typeof(string));
}

private static void printAllPublicPropertiesInCurrentAppDomain(Type typeToFind)
{
    foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
    {
        foreach (Type type in assembly.GetTypes())
        {
            foreach (PropertyInfo info in type.GetProperties())
            {
                if (info.PropertyType == typeToFind)
                {
                    Console.WriteLine("Assembly: {0}, Type: {1}, Property: {2}", assembly.GetName().Name, type.Name, info.Name);
                }
            }
        }
    }
}

EDIT 2

I'm not sure what GetProperties returns by default, but it does have an overload that lets you specify BindingFlags. You could specify:

type.GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)

for all public or private instance and static properties.

Michael Meadows
Would this still work with private fields (i.e. not properties)?
Tim Gradwell
Updated in answer, since I couldn't get it to look right in comments.
Michael Meadows
A: 

I'd want to leverage the existing compiler for this, since otherwise you'd have to implement at least a subset of the C# parser in order to get reasonably reliable answers. Also, personally, I'd like to avoid loading the assemblies involved and using Reflection, since that may cause side effects.

NDepend provides a Code Query Language which allows you to answer this and much more complex questions. Not free, but good.

I think Cecil could be used against the compiled assemblies, with rather more work.

Pontus Gagge
A: 

The feature you're looking for does not exist in VS 2005. The closest feature available is "Find All References" but that will include local variable references which you've said you'd like to exclude.

Can you tell us a bit more as to what you want to do once you've found these fields? If it's just for counting it would be possible to use reflection to find all of the fields and get an accurate count. If it's for something more involved like source changes, you'll likely have to use a parser of sorts.

JaredPar