0

I'm wondering if I can get object which called static method of static class ex:

public class Person
{
    private static class TelephoneLine
    {
        public static string sharedString = string.Empty;
        public static void NotifyOnCall()
        {
            //notify if someone call this person
        }
        public static void Comunicate(Person comunicateWith, string message)
        {
            sharedString = "Sender: " /* Object which called that method */ + " To: " + comunicateWith.Name +
                           " said: " + message;
        }
    }
    public Person(string name)
    {
        Name = name;
    }
    string Name;
    public void CallTo(Person person, string message)
    {
        TelephoneLine.Comunicate(person, message);
    }
    public void ShowCall()
    {
        Console.Write(TelephoneLine.sharedString);
    }
}

}

So is there any possibility to get "Sender" except passing it in parameters of ThelephoneLine.Comunicate(this, comunicateWith, msg) ?

TrN
  • 1,230
  • 2
  • 17
  • 32

4 Answers4

2

It is possible using stack crawling(provided you prevent your static method from being inlined), but it's usually a bad idea.

Retrieving the calling method name from within a method

Doing this for debugging purposes if fine. Doing it because you're too lazy to write it explicitly into your normal program flow is very bad design. So in your case I strongly recommend passing it in manually.


A bit off-topic, but I'm pretty sure your classes shouldn't be static. Static methods are good for simple side effect free functions(See Math or Enumerable for good examples). Your TelephoneLine should at minimum be a Singleton, but IMO you should simply use dependency injection and inject a single instance of it.

Community
  • 1
  • 1
CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
0

The simple answer is no. A lot of .NET's own events (Clicked etc in WinForms or ASP) require you to pass a 'sender' argument.

You can look at the stack to get the name of the method and maybe even the type of the caller, but you certainly cannot obtain the specific object that called the function.

mdm
  • 12,480
  • 5
  • 34
  • 53
0

One way would be to define a common interface between the person and the service and use its contract to pass data:

Generic solution might be overkill to a nested private service class, but you might want to expand on what can make phone calls later and refactor it public, for instance automaticed service calls or something.

public interface ICallable { string CallerIdString(); }

public class Person : ICallable
{
    private static class TelephoneLine
    {
        public static string sharedString = string.Empty;
        public static void NotifyOnCall()
        {
            //notify if someone call this person
        }
        public static void Comunicate<TCaller>(TCaller Caller, Person comunicateWith, string message) where TCaller : ICallable
        {
            sharedString = "Sender: " + Caller.CallerIdString() + " To: " + comunicateWith.Name +
                           " said: " + message;
                           sharedString.Dump();
        }
    }
    public Person(string name)
    {
        Name = name;
    }
    string Name;
    public void CallTo(Person person, string message)
    {
        TelephoneLine.Comunicate<Person>(this, person, message);
    }
    public void ShowCall()
    {
        Console.Write(TelephoneLine.sharedString);
    }

    public string CallerIdString() { return this.Name;}
}
asawyer
  • 17,642
  • 8
  • 59
  • 87
0

The TelephoneLine class shouldn't really be owned by a Person (they're owned by telephone companies!) and they really shouldn't be static (static == code smell).

class TelephoneLine
{
  public TelephoneLine (Person sender, Person receiver)
  {
    m_sender = sender;
    m_receiver = receiver;
  }

  public void Send (Person from, String message)
  {
    if (from == sender)
    {
       output "From: " + m_sender + " To: " + m_receiver + " Message: " + message;
    }
    else
    {
       output "From: " + m_receiver + " To: " + m_sender + " Message: " + message;
    }
  }

  Person m_sender, m_receiver;
};

class Person
{
  public void MakeCall (Person receiver, string message)
  {
     TelephoneLine line = new TelephoneLine (this, receiver);
     line.Send (this, message);
  }
}

In fact, the TelephoneLine object should be owned by something else:

class Exchange
{
  public TelephoneLine MakeCall (Person from, Person to)
  {
    // check that 'to' can receive call first!
    return new TelephoneLine (from, to);
  }
};

class Person
{
  public void MakeCall (Person receiver, string message)
  {
     TelephoneLine line = the_exchange.MakeCall (this, receiver);
     if (line != null)
     {
       line.Send (this, message);
     }
     // else, receiver not listening!
  }
}
Skizz
  • 69,698
  • 10
  • 71
  • 108