Kingthy's blog

最新QQ唠叨:

  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  29 随笔 :: 0 文章 :: 292 评论 :: 10 Trackbacks
也许在某些场合下我们想知道自己的某个方法是被谁(哪个方法)调用的?比如下面的例子:

       /// <summary>
        
/// 正常方法
        
/// </summary>

        static void Method1()
        
{
            DisabledObsoleteMethod();
        }


        
/// <summary>
        
/// 过期方法
        
/// </summary>

        [Obsolete]
        
static void Method2()
        
{
            DisabledObsoleteMethod();
        }


        
/// <summary>
        
/// 禁止过期方法调用此方法
        
/// </summary>

        static void DisabledObsoleteMethod()
        
{
            
//如果调用此方法的方法中有"Obsolete"标记则不允许继续运行
        }


在上面代码中,我们要在DisabledObsoleteMethod函数里限制具有“Obsolete”属性的方法调用,我们如何去做呢?

在.Net中提供了一个"StackFrame"类用于表示当前线程上的函数调用堆栈中的某个具体函数,所以我们通过它就可继续编写我们的DisabledObsoleteMethod函数,代码如下:

        /// <summary>
        
/// 禁止过期方法调用此方法
        
/// </summary>

        static void DisabledObsoleteMethod()
        
{
            StackFrame frame 
= new StackFrame(1);       //偏移一个函数位,也即是获取当前函数的前一个调用函数
            MethodBase method = frame.GetMethod();      //取得调用函数
            
//反射获取其特性
            object[] attributes = method.GetCustomAttributes(typeof(ObsoleteAttribute), false);
            
if (attributes.Length > 0)
            
{
                
//包含有"Obsolete"标记抛出错误或做其它处理
                throw new Exception(string.Format("方法{0}包括有Obsolete属性已被禁止调用",method.Name));
            }


            
//继续做其它操作
        }


到此,当运行Method1时我们的DisabledObsoleteMethod函数就可以正常运作,而Method2就会被抛出异常警告了


因为StackFrame的构造函数可以指定偏移量,所以我们可以使用它获取调用我们的函数时函数调用堆栈里都有些什么函数,也即是可以了解到当前程序的一个流程是如何的,示例代码如下:

    class Test
    
{
        
static void Main()
        
{
            
int offset = 0;
            
do
            
{
                StackFrame frame 
= new StackFrame(offset++);
                MethodBase method 
= frame.GetMethod();
                
if (method == nullbreak;       //如果偏移位置没有函数时,则GetMethod方法返回null
                Console.WriteLine(method.Name);

            }
 while (true);
            Console.Read();
        }

    }


其实.NET已经为我们提供了一个StackTrace类,其可以获取函数调用堆栈里的所有函数的有序集合,通过它我们就能将上面的代码简化为下面的代码了,如下:

   class Test
    
{
        
static void Main()
        
{
            StackTrace trace 
= new StackTrace();
            
foreach (StackFrame frame in trace.GetFrames())
            
{
                Console.WriteLine(frame.GetMethod().Name);
            }

            Console.Read();
        }

    }


两者输出的结果还是一样的,如下:

Main
_nExecuteAssembly
ExecuteAssembly
RunUsersAssembly
ThreadStart_Context
Run
ThreadStart

看来在控制台程序中也是由某个线程委托开始运作的
Tag标签: C#
posted on 2008-04-19 09:20 Kingthy 阅读(2367) 评论(13)  编辑 收藏 所属分类: C#

评论

#1楼  2008-04-19 10:20 代码乱了      
不错的,我在权限系统里面就用到这东东,呵呵
  回复  引用  查看    

#2楼  2008-04-19 10:46 Justin      
顶!
  回复  引用  查看    

#3楼  2008-04-19 12:09 Jacky Zhong      
不错。
  回复  引用  查看    

#4楼  2008-04-19 13:54 Yannic Yang      
有个疑问
那假如过期的Method2调用了未过期的Mehtod3,未过期的Method3调用了DisabledObsoleteMethod()这种情况能否过滤呢?
一定需要用一个foreach判断堆栈上所有函数?
另外,不知道多线程情况下有没有问题
  回复  引用  查看    

#5楼  2008-04-19 15:03 airwolf2026      
不错...又扩大的眼界
  回复  引用  查看    

#6楼  2008-04-19 18:35 Q.Lee.lulu      
学习了
  回复  引用  查看    

#7楼 [楼主] 2008-04-19 20:58 Kingthy      
@Yannic Yang
如果是这种情况则只能一级级往上找了.
多线程也是没有问题的,因为StackFrame是表示当前线程(!!)的调用堆栈中的一个函数调用!l
  回复  引用  查看    

#8楼  2008-04-20 02:30 镜涛      
呵呵,找到自己的调用者不错,这样在写日志文件时就不用传递出错类了,只要负责日志文件的类中得到调用者就行了。
  回复  引用  查看    

#9楼  2008-04-20 08:17 生鱼片      
学习
  回复  引用  查看    

#10楼  2008-04-20 09:52 李战      
路过,雪戏
  回复  引用  查看    

#11楼  2008-04-20 13:45 Windie Chai      
牛,学习了。
  回复  引用  查看    

#12楼  2008-04-21 14:32 流浪的狗      
.net的错误信息就是这么抛出来的, 哈哈.
  回复  引用  查看    


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-04-19 09:27 编辑过