模式 - 没有 else if 的事件调度程序?

发布于 2024-10-25 20:17:35 字数 300 浏览 3 评论 0原文

我正在为 Detours 库创建一个 Python 包装器。该工具的一部分是一个调度程序,用于将所有挂钩的 API 调用发送到各种处理程序。

现在我的代码看起来像这样:

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

这感觉很丑。是否有一种模式可以创建事件调度程序,而无需为每个 Windows API 函数创建 elif 分支?

I'm creating a Python wrapper for the Detours library. One piece of the tool is a dispatcher to send all of the hooked API calls to various handlers.

Right now my code looks like this:

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

This feels ugly. Is there a pattern to create an event dispatcher without my having to create an elif branch for each Windows API function?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

夜声 2024-11-01 20:17:35

一种很好的方法是定义一个类,该类具有与相关 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()

One nice way to do this is to define a class which has methods equating to the relevant API function names, plus a dispatch method which dispatches to the correct method. For example:

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()
梦毁影碎の 2024-11-01 20:17:35

那些如果最终将不得不去某个地方。为什么不这样做:

handler = get_handler(event)
handler.process()

get_handler 中,您将拥有 ifs,每个 ifs 返回一个在 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 条件。

Those if's will eventually have to go somewhere. Why not do it like this:

handler = get_handler(event)
handler.process()

and in the get_handler you'd have your ifs, each returning an object which does its work in the process method.

An alternative would be a map to callables, like this:

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

handlers = {
  "CreateWindowExW" : react_to_create_window_exw
}

and you would use it like this:

handler = handlers[event]
handler()

This way you would not use any if/else conditions.

樱花细雨 2024-11-01 20:17:35

您可以使用调度字典方法。

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

events = {
    "CreateWindowExW": handle_CreateWindowExW
}

events[event]()

这样,您只需添加事件即可,而无需添加不同的 if 语句。

You can use the dispatch dict method.

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

events = {
    "CreateWindowExW": handle_CreateWindowExW
}

events[event]()

This way, you can just add events without having to add different if statements.

嗫嚅 2024-11-01 20:17:35

通常在这种情况下,当您有要执行的预定义操作列表时,请使用地图,例如

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

因此使用地图您可以创建一个非常强大的调度程序

Usually in such cases when you have a predefined list of actions to take, use a map e.g.

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"

Output:

CreateWindowExW
UnkownAction Not Found

so using a map you can create a very powerful dispatcher

[浮城] 2024-11-01 20:17:35

我在这个领域没有找到任何优雅的东西,所以我写了一些东西那让你做:

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

I didn't find anything that was as graceful as it could be in this area, so I wrote something that let's you do:

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

There are some other flavours; docs are here, code is on github, package is on pypi.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文