Question: In C#, when I call a method, I want to be able to detect if it will (or could potentially) call something with a certain attribute. 

For example, when, TheProgram.Run() get's called, I want to know that it will call a MyClass.DoTheWork, which has an attribute [IsRegistered], which calls a private method FormatTheResult() which also has the attribute [IsRegistered].

I've been thinking about it for a while and can't think how it could be achieved. I'm thinking, something like the invert of a stack trace, or registering components with an attribute or aspect, or perhaps leaning on MEF.

Is this possible?

This detection could happen at compile time or a run time, but ideally before the method with the attribute is executed.

Answer: 
Mocking frameworks can do this. It is useful for behavioural tests.

For example, given this setup:

```
public class Calculator {
    private IHelpers _helperMethods;

    public Calculator(IHelpers helper) {
        _helperMethods = helper;
    }

    public int Add(int a, int b) {
        if (_helperMethods.AboveZero(a) && _helperMethods.AboveZero(b)) {
            return a + b;
        }
        throw new Exception("Argument not above zero");
    }
}

public interface IHelpers {
    bool AboveZero(int i);
}

```

Using Moq, you can verify (via a behavioural unit test) that `IHelpers.AboveZero` is called when calling the `Add` method like so:

```
[TestMethod]
public void When_Add_Called_Verify_AboveZero_Called_Too() {
    // Arrange
    var helperMock = new Mock<IHelpers>();    
    helperMock.Setup(x => x.AboveZero(It.IsAny<int>())).Returns(true);

    var calc = new Calculator(helperMock.Object);

    // Act
    var result = calc.Add(1, 2);

    // Assert
    helperMock.Verify(x => x.AboveZero(It.IsAny<int>())); // verify that AboveZero was called.
}

```

The attributes are a different story though..

Is this what you were after?

(Please excuse any compiler errors.. this was typed by hand :/)
This is the way I've found to do it:

```
public static IList<MethodBase> GetCalledMethods(MethodBase methodBase)
{
    IList<MethodBase> calledMethods = new List<MethodBase>();
    var body = methodBase.GetMethodBody();
    Module module = Assembly.GetExecutingAssembly().ManifestModule;
    byte[] bytes = body.GetILAsByteArray();
    using (var stream = new MemoryStream(bytes))
    {
        long streamLength = stream.Length;
        using (var reader = new BinaryReader(stream))
        {
            while (reader.BaseStream.Position < streamLength)
            {
                byte instruction = reader.ReadByte();
                if (instruction == OpCodes.Call.Value
                    || instruction == OpCodes.Callvirt.Value
                    || instruction == OpCodes.Newobj.Value)
                {
                    int token = reader.ReadInt32();
                    var method = module.ResolveMethod(token);
                    calledMethods.Add(method);
                }
            }
        }
    }

    return calledMethods;
}

```