views:

144

answers:

4

I have been pulling my hair out trying to solve this. What I am attempting to do is to build a 'map' of how objects are being used in a bit of code I am working on. Think of it as an enhanced Find Usages. The easiest way to show this is by example:

public class MasterClass
{
    Type1 type1;
    Type2 type2;
    Type3 type3;
    void InitializeData()
    {
        type1 = new Type1(this);
        type2 = new Type2(this);
        type3 = new Type3(this);
    }
}

public class Type1
{
    private MasterClass _master;
    public Type1(MasterClass master)
    {
        _master = master;
    }
    public void Something()
    {
        //use _master.type2 and _master.type3 here
    }
}

public class Type2
{
    private MasterClass _master;
    public Type2(MasterClass master)
    {
        _master = master;
    }
    public void Something()
    {
        //use _master.type3 here
    }
}

public class Type3
{
    private MasterClass _master;
    public Type3(MasterClass master)
    {
        _master = master;
    }
    public void Something()
    {
        //use _master.type1 and _master.type2 here
    }
}

What I am trying to do is get a mapping or report that, in the example's case, would give something like:

Type1 used by: {Type3}

Type2 used by: {Type1, Type3}

Type3 used by: {Type1, Type2}

If I can get it into a dictionary then I am home. :-)

What I've tried:

I have tried going over the assemblies, each type, each method then pulling the IL arrays and then trying to parse the operands with no luck. I have even tried going over the source files with some regular expressions but I have thousands of classes to go over, written in several different styles which means I will missed some references.

I can use Reflector &&/|| Resharper to get a single reference at a time but I would like to get them all at once.

Any suggestions?

+2  A: 

It's not easy. You will have to get an instance of MethodInfo, PropertyInfo, FieldInfo, etc for all of the following:

  • methods
  • types
  • properties (get and set)
  • event (add and remove)

Then you'll need to parse the IL and call the ResolveMethod instance on the Module instance that the type being examined is in, and look to see if the instance corresponds to the MethodInfo for your method that you are trying to determine the use of.

EDIT:

Like "Find All References" in Visual Studio, this will only find direct references. If you also want to find indirect references (ex: method1 references method2, and method2 references method3 - you would like to see that there is a connection from method1 to method3), you'll need to do this with recursion.

Gabriel McAdams
+5  A: 

I suggest using NDepend for this, as it is tailor made to the problem you're describing. Doing this in code is going to be quite a lot of work.

sixlettervariables
At your recommendation I have downloaded the trail of NDepend and have played with it but I have not found a way to generate the report I need. I may have to play with it some more.
Randy K
The Dependency Matrix didn't suit your needs? Or does it just not go into the detail you need?
sixlettervariables
With hundreds of classes in a namespace and references to objects in sibling namespaces neither the matrix nor the graph is very usable. One of the smaller namespaces I must deal with generate a matrix that is 640 x 640. To include all of the objects I would look at a matrix of 4300+ x 4300+.Adding to this is the fact that the trail does not let you zoom in. So for the graph I see a huge blob where I cannot get down to individual classes. :-(But again I haven't had a lot of time to look at it.
Randy K
I have found I can find the information I need using NDepend using the CDL language.
Randy K
That is quite a large project, I do not envy testing said project.
sixlettervariables
A: 

If you are just searching for a tool, Reflector might do it with some add-ins.

Here you will find a wide range of add-ins: http://reflectoraddins.codeplex.com/

Some plugins like FileGenerator can copy Reflector output directly into a file.

Ucodia
A: 

Try Jb Evain's CILReader or Cecil

He mentions nice solution for simillar problem here

Pavel Savara