Elixir 跟踪“使用”其他模块的模块

Elixir 跟踪“使用”其他模块的模块,elixir,Elixir,我试图跟踪编译时使用另一个模块的所有模块,并在运行时获取所有这些模块的列表: 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 BaseMod

我试图跟踪编译时使用另一个模块的所有模块,并在运行时获取所有这些模块的列表:

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]

我一直在试图找到一种方法来实现这一点,但仍然完全不知道如何做到这一点。通过查看,建议使用
协议执行此操作。但在为此奋斗了大约一个小时后,我也无法让它与协议一起工作

我也一直在查看
注册表
模块,看看我是否可以使用它来完成这项工作,但它看起来主要是为处理进程而设计的


任何帮助都将不胜感激。提前谢谢

如果您的基本模块使用行为,则以下解决方案是可能的

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]
defmodule BaseModule do
@回调foo()::any()
定义宏\uuuu使用\uuuu(\u选项)do
引述
#使用一种行为是相当标准的,这给了我们以后可以检测到的东西。
@行为(模块)
#需要其他设置吗
结束
结束
def children()做什么
(对于{module,}Enum.filter(&is_child?/1)
结束
def是子模块?(模块)do
模块。模块信息[:属性]
|>关键字.get(:行为,[])
|>枚举成员(模块)
结束
结束
defado模块
使用基本模块
结束
BaseModule.children()
#=>[A]

您的use宏是否在目标模块中包含行为。需要对目标模块产生一些影响,因为
\uu using\uuuuuu
宏可能不会返回任何效果,并且无法检测,这很好!但我唯一的问题是
:code.all\u loaded()
并不总是列出所有模块(因为VM延迟加载它们),我希望有其他东西总是能给出相同的结果。这很公平,我也没有想过。但你无法找到未加载的模块。本质上,他们不会“使用”BaseModule,因为他们的使用行不会被调用。这仍然是一个很好的解决方案。谢谢你的支持我们的答案。