Могу ли я получить вызывающий экземпляр из метода с помощью отражения/диагностики?

Есть ли способ через System.Reflection, System.Diagnostics или другой способ получить ссылку на фактический экземпляр, который вызывает статический метод, не передавая его самому методу?

Например, что-то в этом духе

class A
{
    public void DoSomething()
    {
        StaticClass.ExecuteMethod();
    }
}

class B
{
    public void DoSomething()
    {
        SomeOtherClass.ExecuteMethod();
    }
}
public class SomeOtherClass
{
    public static void ExecuteMethod()
    {
        // Returns an instance of A if called from class A
        // or an instance of B if called from class B.
        object caller = getCallingInstance();
    }
}

Я могу получить тип, используя System.Diagnostics.StackTrace.GetFrames, но есть ли способ получить ссылку на реальный экземпляр?

Я знаю о проблемах с отражением и производительностью, а также о статических вызовах, и что это, как правило, возможно, даже почти всегда, неправильный подход к этому. Частично причина этого вопроса в том, что мне было любопытно, выполнимо ли это; в настоящее время мы передаем экземпляр.

ExecuteMethod(instance)

И я просто задавался вопросом, возможно ли это и все еще иметь доступ к экземпляру.

ExecuteMethod()

@Steve Cooper: я не рассматривал методы расширения. Некоторые варианты этого могут сработать.


person Scott Nichols    schedule 18.09.2008    source источник


Ответы (5)


Я не верю, что вы можете. Даже классы StackTrace и StackFrame просто предоставляют информацию об именах, а не доступ к экземплярам.

Я не совсем уверен, почему вы хотите это сделать, но знайте, что даже если бы вы могли это сделать, это, вероятно, было бы очень медленным.

Лучшим решением было бы передать экземпляр в локальный контекст потока перед вызовом ExecuteMethod, который вы можете получить внутри него, или просто передать экземпляр.

person Aaron Jensen    schedule 18.09.2008

Подумайте о том, чтобы сделать метод методом расширения. Определите это как:

public static StaticExecute(this object instance)
{
    // Reference to 'instance'
}

Называется так:

this.StaticExecute();

Я не могу придумать способ сделать то, что вы хотите сделать напрямую, но я могу только предложить, если вы что-то найдете, вы следите за статическими методами, у которых их не будет, и анонимными методами, у которых будут экземпляры. автоматически сгенерированных классов, что будет немного странно.

Мне интересно, следует ли вам просто передать вызывающий объект в качестве правильного параметра. В конце концов, static — это намек на то, что этот метод не зависит ни от чего, кроме своих входных параметров. Также обратите внимание, что этот метод может быть сукой для тестирования, поскольку любой тестовый код, который вы пишете, не будет иметь того же вызывающего объекта, что и работающая система.

person Steve Cooper    schedule 18.09.2008
comment
это должен быть ответ - person NewBie1234; 20.01.2019
comment
Фактически это передача экземпляра статическому методу (которого в вопросе просили не делать). Он просто передает его в другом варианте синтаксиса. - person Stijn Van Antwerpen; 04.06.2019
comment
@StijnVanAntwerpen да, это правильно. Но исходный вопрос - плохой вопрос. Если вы хотите использовать переменную, просто передайте ее — не используйте отражение или кадры стека. Это обеспечивает синтаксический подход для создания похожего кода, но на самом деле просто не делайте этого. - person Steve Cooper; 17.06.2019

В случае статического метода, вызывающего ваш статический метод, нет вызывающего экземпляра.

Найдите другой способ выполнить то, что вы пытаетесь сделать.

person therealhoff    schedule 18.09.2008

Просто пусть ExecuteMethod принимает объект. Тогда у вас есть экземпляр, несмотря ни на что.

person Jason Punyon    schedule 18.09.2008

Я чувствую, что я что-то упускаю, здесь. Статический метод можно вызывать буквально из любого места. Нет никакой гарантии, что экземпляр класса A или класса B появится где-либо в стеке вызовов.

Должен быть лучший способ добиться того, что вы пытаетесь сделать.

person Mark Bessey    schedule 18.09.2008