Patterns - Event Dispatcher без других, если? - PullRequest
1 голос
/ 25 марта 2011

Я создаю оболочку Python для библиотеки Detours.Одним из инструментов является диспетчер, который отправляет все перехваченные вызовы API различным обработчикам.

Сейчас мой код выглядит так:

if event == 'CreateWindowExW':
    # do something
elif event == 'CreateProcessW':
    # do something
elif ...

Это выглядит ужасно.Существует ли шаблон для создания диспетчера событий без необходимости создавать ветку elif для каждой функции Windows API?

Ответы [ 5 ]

4 голосов
/ 25 марта 2011

Один хороший способ сделать это - определить класс, в котором есть методы, приравненные к соответствующим именам функций API, плюс метод отправки, который отправляет правильный метод.Например:

class ApiDispatcher(object):

    def handle_CreateWindowExW(self):
        # do whatever

    def handle_CreateProcessW(self):
        # do this one

    def dispatch(self, event):
        method = getattr(self, 'handle_%s' % event)
        method()
2 голосов
/ 25 марта 2011

Вы можете использовать метод dict dispatch.

def handle_CreateWindowExW():
    print "CreateWindowExW"     
    #do something

events = {
    "CreateWindowExW": handle_CreateWindowExW
}

events[event]()

Таким образом, вы можете просто добавлять события, не добавляя различные операторы if.

2 голосов
/ 25 марта 2011

Те, кто в конечном итоге, должны будут куда-нибудь пойти. Почему бы не сделать это так:

handler = get_handler(event)
handler.process()

и в get_handler вы получите свои if, каждый из которых возвращает объект, который выполняет свою работу в методе process.

Альтернативой может быть карта для вызываемых, например:

def react_to_create_window_exw():
   # do something with event here
   pass

handlers = {
  "CreateWindowExW" : react_to_create_window_exw
}

и вы бы использовали это так:

handler = handlers[event]
handler()

Таким образом, вы не будете использовать условия if / else.

1 голос
/ 25 марта 2011

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

def CreateWindowExW():
    print 'CreateWindowExW'

def CreateProcessW():
    print 'CreateProcessW'

action_map = {
    'CreateWindowExW': CreateWindowExW,
    'CreateProcessW': CreateProcessW
}

for action in ['CreateWindowExW', 'UnkownAction']:
    try:
        action_map[action]()
    except KeyError:
        print action, "Not Found"

Выход:

CreateWindowExW
UnkownAction Not Found

, поэтому с помощью карты вы можете создатьочень мощный диспетчер

0 голосов
/ 24 ноября 2018

Я не нашел ничего настолько изящного, как могло бы быть в этой области, поэтому я написал что-то , что давайте вам сделаем:

from switcheroo import Switch, default

switch = Switch({
    'foo': lambda x: x+1,
    default: lambda x: x-1,
})

>>> switch['foo'](1)
2
>>> switch['bar'](1)
0

Есть и другие вкусы; документы здесь , код на github , пакет на pypi .

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