如何在 Elixir 中猴子补丁模块功能

问题描述 投票:0回答:2

我有一个 Elixir 模块,可以导入一些函数。我想用我自己的函数来猴子修补其中一个函数。那可能吗?我该怎么做?

更新示例

我的具体示例是,对于任务 Mix.Tasks.Deps.Compile,我想向“编译”功能添加一些功能。

https://github.com/elixir-lang/elixir/blob/master/lib/mix/lib/mix/tasks/deps.compile.ex

Mix.Tasks.Deps.Compile 模块相当深入地融入到 Mix 框架中。我想做最小的改变,同时添加我想要的额外功能。我想要添加的功能是 cond do 块的另一个条件。

elixir
2个回答
10
投票

简单的答案是:你不能。 BEAM 上没有猴子修补的概念。

更长的答案是 BEAM 中的模块是延迟加载的,因此您可以用您自己的实现替换模块(但是整个模块,而不仅仅是单个函数)。但我真的不确定这是否是正确的方法。


0
投票

您可以通过反编译要进行猴子修补的模块,更改 Erlang 抽象代码,然后重新加载该模块来完成此操作。找到要更新的特定条件分支会有点困难,但并非不可能。我使用这种方法将私有函数与另一个函数包装起来,以便操纵私有函数的返回值。

{_, beam_, } = :code.get_object_code(Mix.Tasks.Deps.Compile)
{:ok, {_, [{:abstract_code, {:raw_abstract_v1, code}}]}} = :beam_lib.chunks(beam), ~w/abstract_code/a)
# Do the manipulation to the abstract code here

# Then recompile and load the binary code
{:ok, modname, binary} = :compile.forms(code)
:code.load_binary(modname, [], binary)

我不会对这是对还是错做出任何判断,这可能只是达到目的的一种手段。以下库使用此方法: Patch、mecks 以及可能更多的模拟库。

© www.soinside.com 2019 - 2024. All rights reserved.