English 中文(简体)
使用堆栈跟踪来推断方法的调用者
原标题:
  • 时间:2008-11-25 18:13:06
  •  标签:

编辑:警告-我现在意识到以下技术通常被认为是不好的想法,因为它为了看起来整洁而创建了隐藏的依赖关系。


我最近发现您可以使用StackTrace推断方法的调用者的信息。

这使您能够创建一个看似“酷炫”的API,您只需调用一个方法,而不必在调用中传递任何显式参数,该方法会根据StaockTrace自行确定要执行的操作。

这是一件不好的事情吗?如果是,为什么?

例子:

public class Cache {
  public Object CheckCache()
  {
    Object valueToReturn = null;
    string key = GenerateCacheKeyFromMethodPrototype(new StackTrace().GetFrame(1).GetMethod()); //frame 1 contains caller
    if(key is in cache) valueToReturn = itemFromCache;

    return valueToReturn;   
  }
}

public class Foo { 
  private static Cache cache = new Cache();

  public Blah MethodFoo(param1, param2...)
  {
    Blah valueToReturn = cache.CheckCache(); //seems cool!
    if(valueToReturn == null)
    {
      valueToReturn = result of some calculation;
      //populate cache
    }

    return valueToReturn;
  }
}

我相信以上的伪代码中可能会有错误,但您应该能够理解我的意思。


编辑:感谢大家的回复。 (Bianji: Ganxie dajia de huiying.)

最佳回答

这件事有两个不做的原因:

  • It s slow
  • It s creates a brittle solution.

如果你想这么做,最好使用支持面向方面编程的工具,如Castle的动态代理。

问题回答

另一个问题是编译器在优化过程中可能会“内联”您的方法,例如。

void MethodA() {
    MethodB();
}

void MethodB() {
   foo();
}

变得:

void MethodA() {
   foo();
}

这显然是个问题,因为对于foo的即时调用者不再是MethodB,而是MethodA。 但是,你可以在你的方法上放置一个属性,以防止它被内联:

[MethodImpl( ... NoInline )]

我记不清确切的参数。

奥辛

这很不好,因为当我调用函数时,我无法知道它的功能。我无法测试函数,因为我的测试将从不同的函数调用它,这可能会引发不同的行为。

这很糟糕,因为现在有一个“隐形”的合约,我必须遵守当调用函数的时候。我不仅要确保传递了正确的参数,还要确保当前函数的名称是正确的。如果我将函数调用包装在匿名 Lambda 函数中会怎样?突然间,我改变了程序的行为,而我并没有预料到这一点,现在我可以花费下一天来调试为什么程序突然神奇地崩溃了。

重载函数会发生什么?你区分它们吗?同名但在不同类中的函数?有“特殊”名称的函数,例如构造函数、终结器、运算符或Lambda表达式吗?

当编译器内联函数时怎么办?

这对我来说似乎一点也不酷。你为什么想要在方法本身中放置获取所需state的每种可能方式?这就像是依赖注入的反模式。不要走这条路。





相关问题
热门标签