我正在尝试在编译时跟踪use
另一个模块的所有模块,并在运行时获取所有这些模块的列表:
defmodule BaseModule do
defmacro __using__(_) do
quote do
# common behaviour
end
end
end
defmodule A do
use BaseModule
end
defmodule B do
use BaseModule
end
defmodule C do
use BaseModule
end
通过调用类似的东西在运行时获取它们:
BaseModule.children()
#=> [A, B, C]
我一直试图找到一种方法来实现这一目标,但仍然完全不知道如何做到这一点。通过this thread on the elixir-lang mailing list,@josevalim建议使用Protocols
执行此操作。但经过大约一个小时的努力,我无法让它与协议一起工作。
我也一直在查看Registry
模块,看看我是否可以使用它完成此任务,但看起来它主要用于处理进程。
任何帮助都将受到高度赞赏。提前谢谢!
答案 0 :(得分:3)
如果基本模块使用某种行为,则可以使用以下解决方案。
defmodule BaseModule do
@callback foo() :: any()
defmacro __using__(_opts) do
quote do
# Fairly standard to use a behaviour and gives us something to detect later.
@behaviour unquote(__MODULE__)
# Any other setup required
end
end
def children() do
(for {module, _} <- :code.all_loaded(), do: module)
|> Enum.filter(&is_child?/1)
end
def is_child?(module) do
module.module_info[:attributes]
|> Keyword.get(:behaviour, [])
|> Enum.member?(__MODULE__)
end
end
defmodule A do
use BaseModule
end
BaseModule.children()
#=> [A]