是否可以装饰事件处理程序来执行登录检查?

时间:2015-06-30 22:03:03

标签: c# .net python-decorators

我有几个执行不同操作的事件处理程序(例如发出HTTP请求)。我想检查用户是否在从事件处理程序执行代码之前登录。

目前我这样做:

private void Publish_Click(object sender, RibbonControlEventArgs e)
        {
            try
            {
                var temp = GlobalVariables.sessionData["loggedUser"];
            }
            catch (Exception ex) {

                if (ex is NullReferenceException || ex is KeyNotFoundException) 
                {
                    MessageBox.Show("Please log in");
                    return;
                }

                throw;
            } 

            publishBTaskPane = new BTaskPane();
            myTaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(publishBTaskPane, "Publish");
            myTaskPane.VisibleChanged += new EventHandler(myTaskPane_VisibleChanged);
            myTaskPane.Visible = true;

        }

我想在事件处理程序之外保留'try'子句。

在Python中,您可以使用装饰器。

def login_required(handler):
    """
    Decorator which performs a user authentication before a particular handler is executed.
    """
    def check_login(self, *args, **kwargs):
        if not self.user:
            return self.redirect('/login')
        else:
            return handler(self, *args, **kwargs)
    return check_login

class LogoutHandler(BaseHandler):
    """
    Terminate the user session and return them to the login screen.
    """
    @login_required
    def get(self):
        self.auth.unset_session()
        if not self.request.user_agent:
            return self.response.write('OK')
        self.redirect('/login')

是否有可能在C#中做类似的事情,所以我不必在每个事件处理程序中重复try子句?

2 个答案:

答案 0 :(得分:1)

这将是一种通用的答案,因为我没有完整的问题背景来确定答案,但希望你可以根据自己的需要进行调整。

首先,获得最接近的方法是创建自己的注释并让它包装方法,但这需要一些额外的学习(假设你还不知道它)才能完成。< / p>

最简单的方法可以创建一个您在这些处理程序中首先调用的函数:

public boolean notLoggedIn() {
   try {
      var temp = GlobalVariables.sessionData["loggedUser"];
      return false;
   }
   catch (Exception ex) {
      if (ex is NullReferenceException || ex is KeyNotFoundException) {
          MessageBox.Show("Please log in");
          return true;
      }

      throw;
   }
}

由处理程序使用:

private void Publish_Click(object sender, RibbonControlEventArgs e) {
   if(notLoggedIn())
      return;

   publishBTaskPane = new BTaskPane();
   myTaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(publishBTaskPane, "Publish");
   myTaskPane.VisibleChanged += new EventHandler(myTaskPane_VisibleChanged);
   myTaskPane.Visible = true;
}

另一件要尝试的是Execute Around Method模式。您可以使用通用登录检查程序运行实际方法所执行的lambda。所以,使用这个:

public void ifLoggedIn(Action action) {
   try {
      var temp = GlobalVariables.sessionData["loggedUser"];
      action();
   }
   catch(Exception e) {
      if (ex is NullReferenceException || ex is KeyNotFoundException) {
          MessageBox.Show("Please log in");
          return true;
      }

      throw;
   }
}

这样的处理程序可以使用:

public void Public_Click(object send, RibbonControlEventArgs e) {
   ifLoggedIn( () => {
      publishBTaskPane = new BTaskPane();
      myTaskPane = Globals.ThisAddIn.CustomTaskPanes.Add(publishBTaskPane, "Publish");
      myTaskPane.VisibleChanged += new EventHandler(myTaskPane_VisibleChanged);
      myTaskPane.Visible = true;
   }
}

还有一些其他方法可以轻松应用“包装”我想到的,但我认为任何方法都不能很好地解决您的问题。

答案 1 :(得分:0)

C#中Python装饰器的等价物是member attribute。一个区别是属性没有执行,只是通过反射访问。我想知道,由于C#支持为一个事件提供多个处理程序,因此可以为所有事件设置一个处理程序,以检查其他处理程序是否具有此属性,如果是,则执行登录检查。

相关问题