在Elixir中动态加载/卸载模块,类似于插件系统

Rod*_*odi 4 elixir

我想创建类似插件系统的东西:一堆动态加载/卸载的模块,添加我插入/删除它们.

像这样的东西:

# plugin1.eex
defmodule MyApp.Plugins.Plugin1 do

  def plugin_main_func(arg1, arg2) do
    # some stuff
  end
end

# plugin2.eex
defmodule MyApp.Plugins.Plugin2 do

  def plugin_main_func(arg1, arg2) do
    # some stuff 2
  end
end


# plugin3.eex
defmodule MyApp.Plugins.Plugin3 do

  def plugin_main_func(arg1, arg2) do
    # some stuff 3
  end
end
Run Code Online (Sandbox Code Playgroud)

它们将具有相同的通用功能 - "plugin_main_func" - 每个插件的实现方式都不同.在我的应用程序的某个地方我会有这个:

plugins = load_plugins()
Enum.each plugins, &(&1.plugin_main_func(1, "fdafdsfds"))
Run Code Online (Sandbox Code Playgroud)

然后我可以通过创建或删除适当的模块或文件来添加或删除插件.如果没有进行硬编码/添加/在应用程序中作为一个字符串列表的地方删除它们的名称以及.

我怎么能得到这个?

更新:

鉴于插件必须存在于MyApp.Plugins并且具有一个功能 plugin_main_func,我如何观察它们当前存在的插件列表?我只是想避免在某处硬编码他们的名字并加载或运行它们只有这两个条件足以找到所有的插件.

当我动态或半动态地找到它们时,我想以某种方式调用plugin_main_func每个插件.不知道插件的数量和它们的确切名称.怎么样?

我很好在编译之前加载它们,而不是在运行时.

Ale*_*kin 8

回答标题中所述的问题:是的,可以在Elixir中动态加载/卸载模块.使用例如编译代码Code.ensure_compiled/1并使用Erlang的code模块清除它:

:code.delete MyApp.Plugins.Plugin1
:code.purge MyApp.Plugins.Plugin1
Run Code Online (Sandbox Code Playgroud)

回答整个问题:你做错了.Elixir是一种编译语言,你正在滥用它.在运行时编译绝对不是Elixir的好处.

您只需要保留一个"已加载"插件列表,以伪造您尝试实现的行为.load会将模块名称添加到列表中,unload并将其从那里删除.就是这样.您不需要在运行时加载/卸载任何内容:它非常无效,危险且反惯用.如果你需要良好的运行时插件支持 - 去,,甚至是.


要在运行时获取已加载模块的列表,可以使用:

:application.get_key(:my_app, :modules)
Run Code Online (Sandbox Code Playgroud)

您可以将插件限制为所需的命名空间(例如MyApp.Plugins),并按该名称过滤列表.

  • 并且,为了上帝的缘故,请停止滥用代码格式化程序(反引号)以强调.如果您无法调整键盘以获得正确的引号("") - 请使用markdown的强调格式. (2认同)