2010-12-08 5 views
2

나는 메시지 버스가 있고, 클래스는 예를 들어, 메시지 버스에 많은 방법을, 구독 : 내가 원하는클래스 레벨의 데코레이터를 올바르게 사용하는 방법은 무엇입니까?

class BookingService(object): 
    def start(self): 
     self.msg_bus.login(self.user, self.password) 
     self.msg_bus.subscribe('/broadcast/aliveResponse', self.handleAliveResponse) 
     self.msg_bus.subscribe('/broadcast/musicInfoUpdated', self.handleMusicInfo) 
     self.msg_bus.subscribe('/broadcast/radioOnline', self.handleRadioOnline) 
     self.msg_bus.subscribe('/broadcast/radioOffline', self.handleRadioOffline) 
     self.msg_bus.subscribe('/broadcast/online', self.handleBroadcastOnline) 
     self.msg_bus.subscribe('/proxy/aliveResponse', self.handleEvent) 
     self.msg_bus.subscribe('/proxy/online', self.handleProxyOnline) 
     self.msg_bus.subscribe('/proxy/radioReady', self.handleEvent) 
     self.msg_bus.subscribe('/proxy/radioUpdate', self.handleEvent) 
     self.msg_bus.subscribe('/proxy/radioClosed', self.handleEvent) 
     self.msg_bus.subscribe('/message_bus/detached', self.handleDetached) 
     self.msg_bus.run() 

그것은 작동하지만, 각 방법에 대한 메시지 경로 무엇인지 이해하기 어렵습니다, 이 것이

class BookingService(object): 

    @subscribe('/broadcast/aliveResponse') 
    @subscribe('/broadcast/onLine') 
    def handleEvent(self, dest, data): 
     print dest, data 

    @subscribe('/proxy/aliveResponse') 
    def handleAnotherEvent(self, dest, data): 
     print dest, data 

처럼 보인다하지만, 여기에 무엇보다도 먼저 해결하는 어려움이다, 방법 메시지 버스에 가입하기 위해 장식을 사용하는 것입니다의 msg_bus 속성은 인스턴스, 즉 자기에 속한다. 클래스 레벨에서 self.msg_bus를 가져올 수 없습니다. 이 문제를 해결하기 위해,이처럼 쓸 수 있습니다 :

class BookingService(object): 

    subscribations = [] 
    def subscribe(dest): 
     """Decorator for subscribing function to destination 

     """ 
     def callee(func): 
      subscribations.append((dest, func)) 
      return func 
     return callee 

    def subscribe_all(self): 
     for dest, func in self.subscribations: 
      self.msg_bus.subscribe(dest, func) 

    @subscribe('/broadcast/aliveResponse') 
    def handleEvent(self, dest, data): 
     print dest, data 

    def start(self): 
     self.subscribe_all() 

나는 BookingService.subscribations에 가입을 수집하고 subscribe_all 나중에 msg_bus에 추가하려고 노력하지만, 여기에 문제가 온다. 오류가 발생했습니다

subscribations.append((dest, func)) 
NameError: global name 'subscribations' is not defined 

구독이 구독 기능의 범위에없는 것 같습니다.이 문제를 해결하는 방법은 무엇입니까?

+0

이 작업을 가장 잘하려면 메타 클래스 (또는 수퍼 클래스)가 필요합니다. –

답변

1

인스턴스의 목록에 넣는 대신 함수 또는 클래스의 목록에 넣으십시오.

class BookingService(object): 

    def subscribe(dest): 
     """Decorator for subscribing function to destination 

     """ 
     def callee(func): 
      if not hasattr(func, 'subscriptions'): 
       func.subscriptions = [] 
      func.subscriptions.append((dest, func)) 
      return func 
     return callee 

    def subscribe_all(self): 
     for classmember in dir(self): 
      for dest, func in getattr(getattr(self, classmember), 'subscriptions', []): 
       self.msg_bus.subscribe(dest, func) 

    @subscribe('/broadcast/aliveResponse') 
    def handleEvent(self, dest, data): 
     print dest, data 

    def start(self): 
     self.subscribe_all() 

그러나 바인딩되지 않은 메서드에는 여전히 문제가있을 수 있습니다. "자아"가 무엇을 의미하는지주의하십시오.

또한

0

이동 클래스 정의 외부에 "구독", 또는 "_subscribe을"의 이름을 변경하거나 self.subscribe()로 호출되는 대처하기 (self.subscribe()이 작동 순간에 있지만 기대하지 방법) 할 수 있습니다 클래스 본문에서 구독을 정의하면 클래스 본문이됩니다. 그러나 사용할 때는 전역으로 사용합니다. 메소드에서 가져와야하지만, 클래스가 작성되기 전에 발생하므로 그렇게 할 수 없습니다.

함수의 특성으로 설정할 수도 있고 함수와 대상 간의 매핑을 사용하여 전역 사전을 만들 수도 있습니다. 두 경우 모두 subscribe_all 메소드의 클래스에있는 모든 함수를 거쳐 구독이 있는지 확인해야합니다.

관련 문제