2

I have a requirement where I need to know the calling method to the GetEnumerator().

The best way I could think would be possibly overriding the default behaviour to GetEnumerator to one that I create i.e GetEnumerator([CallerMemberName]string caller = null) but I cannot seem to do this as anything calling it still goes to the original one.

public class MyItems : IEnumerable<string>
{
    private List<string> items = new List<string>();
    public MyItems()
    {
        items.Add("One");
        items.Add("Two");
        items.Add("Three");
        items.Add("Four");
        items.Add("Five");
        items.Add("Six");
    }

    public IEnumerator<string> GetEnumerator()
    {
        return items.GetEnumerator();
    }

    public IEnumerator<string> GetEnumerator([CallerMemberName]string caller = null)
    {
        var method = caller;
        return items.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }
}

Example of some calling code could be

private void button1_click(object sender,EventArgs e)
{
    MyItems items = new MyItems();
    foreach (var item in items)
    {

    }
}

The aim is that I would want to know for example "button1_click" in the GetEnumerator() method

default
  • 11,485
  • 9
  • 66
  • 102
jclarkson
  • 169
  • 3
  • 11
  • what does the caller code look like? – default Mar 21 '13 at 11:06
  • Do not implement IEnumerable directly. Instead, have a method GetEnumerable(string caller) that returns an IEnumerable and take the caller as argument. – Guillaume Mar 21 '13 at 11:07
  • Not implementing IEnumerable is not an option as we are implementing an interface that already implements IEnumerable. The interface is Microsoft IDBSet interface. We need to know the calling method from a generic repositiory so that we can react accordingly but would like to keep the separation between the repository layer and the DBSets etc... – jclarkson Mar 21 '13 at 11:35

2 Answers2

2

I don't think it's possible to do exactly what you want to do, since foreach, to my knowledge, always calls the GetEnumerator() without any arguments. However, I see two possibilities to your issue

You can use a StackTrace to get the calling method:

public IEnumerator<string> GetEnumerator()
{
    StackTrace stackTrace = new StackTrace();
    Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);
    return items.GetEnumerator();
}

or you can use another method instead of the GetEnumerator() which takes the [CallerMemberName] attribute.

public IEnumerable<string> Iterate([CallerMemberName]string caller = null)
{
    Console.WriteLine(caller);
    return items;
}

foreach (var myItem in items.Iterate())
{
    //..
}
default
  • 11,485
  • 9
  • 66
  • 102
0

seems like , you need to use StackTrace Class

StackTrace st = new StackTrace();
        var fr = st.GetFrames();
        if(fr != null && fr.Any() &&fr.Count() >1)
        {
            MessageBox.Show(fr.ElementAt(1).GetMethod().Name);
        }
TalentTuner
  • 17,262
  • 5
  • 38
  • 63