This project is read-only.

How can I find the type of the object which calls a method (which is generally not the same type than the IMemberReference.DeclaringType)?

Jul 22, 2009 at 12:03 PM

Hi,

I am actually working on a reflector add-in. This add-in is a smart analyzer which can be configured to find some relationships between methods. That is quite the same that the .NET Reflector analyze does but the main improvement compared to the current static analyzers is:

Consider the simple following example:

namespace SimpleExemple
{
    public class Company
    {
        public void Working()
        {
            Employee e = new Employee();
            e.Go();
            e.Work();
            e.Leave();
        }
    }

    abstract public class Person
    {
        abstract public void Go();

        abstract public void Work();

        abstract public void Leave();
    }

     public class Employee:Person
    {

        public override void Go()
        {
            // Go to the company
        }

        public override void Work()
        {
            // Do some work
        }

        public override void Leave()
        {
            // Go back home
        }
    }

    public class Manager:Person
    {

        public override void Go()
        {
            // Go to the company by car (big one)
        }

        public override void Work()
        {
            // Do some manager work
        }

        public override void Leave()
        {
            // Go back home by car (big one)
        }
    }

}

A Manager is a Person and an Employee is a Person too.

A Person can Goes (to the company) Works (in the company) and Leaves (the company).

The company “Working” method creates a new Employee then the employee Goes, Works and Leaves.

In this example a Manager never works (the function Manager.Works() is never called, it is just an example I have nothing against the managers ;) ).

Let us analyze the Manager.Work() method in .NET Reflector:

SimpleExample.Manager.Work() : Void

     Depends On

     Used By

           SimpleExample.Company.Working() : Void

 

Actually, the Manager.Work() method is not called in the Company.Working() method. But the Manager.Work() overrides the base method Person.Work() and it is this method which is referenced in the code. This is the principle of virtual (or abstract) methods; the right method call is determinate on runtime.

I want to circumvent that problem finding the strong typed object type which actually calls the Work() method. If I find the Employee type, I will know that is the Employee.Work() which is called.

So that is my question: How can I find the type of the object which calls a method (which is generally not the same type than the IMemberReference.DeclaringType)?

The disassembler in .NET Reflector gives me the information if I disassemble the Company.Working() method: when I put my mouse over the ”e“ local variable I can see “Employee e // Local Variable”. But I cannot retrieve this information.

Do you know how can I find it? Thanks.

Aug 7, 2009 at 2:11 AM

I'm not 100% sure I understand what you are looking for, but maybe this will help.

You metion... "when I put my mouse over the ”e“ local variable I can see “Employee e // Local Variable”. But I cannot retrieve this information.". 

I'm guessing you want to create some smart mapping that 'knows' that SimpleExample.Company.Working() uses an instance of Employee not just any child of Person. If that is what you are trying to do, then you picked a nice challenge for yourself. 

You can see why Reflector does what it does if you look at the IL version of your SimpleExample.Company.Working().   The call to Work() is a callvirt of the Person.Work() ... it isn't simple a call to Employee.Work() like the C# makes it look like.  So my guess is you're going to need to parse the IL and decipher the callvirt instructions in a smarter way to determine a better type mapping.  Its doable ... but I think you're going to need to get real familiar with IL and how it works (but maybe not).  The most beneficial thing in the line: e.Work(); maybe that the variable type of e is Employee.

You might be able to use the LanguageWriterHelper to help you determine what the C# is showing, for example the e.Work() is a IMethodInvokeExpression, that has a Method and a Target.  The Target is an IVariableReferenceExpression ... that has a VariableType of an ITypeReference of SimpleExample.Employee.

Information on the LanguageWriterHelper:  http://jasonhaley.com/blog/post/2008/12/02/Reflector-Addin-LanguageWriterHelper.aspx

Good luck!