Elixir - 在“use”语句中组合字符串不起作用

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

我目前正在尝试

use
我自己的模块中的 Interceptor 库。为此,我需要提供一个配置参数。此参数由一个映射组成,其中键是字符串,表示必须拦截哪些模块的哪些功能,值由一个列表组成,其中包含有关应如何进行拦截的信息。我专门在寻找钥匙方面的帮助。

正如我所解释的,我的键是代表要拦截的函数的字符串。它们的格式如下:

moduleName.functionName/arity
。当只是硬编码这个字符串时,一切正常。但是,我希望能够动态地形成这个字符串。更具体地说,我想动态填写模块名称。这样做的原因是我想在稍后阶段使用宏注入这段代码,然后我不会事先知道模块。我将能够事先知道和硬编码的功能名称和数量。

我的代码目前如下所示:

use Interceptor, config: %{
    String.slice(to_string(__MODULE__), 7..-1) <> ".someFunction/2" => [
      before: "SpecialInterceptor.intercept_before/1",
      after: "SpecialInterceptor.intercept_after/2"
    ]
  }

注意,我之所以对字符串进行切片是因为

__MODULE__
在模块名称前加上“Elixir”。例如,
Elixir.ModuleName
。因此,我需要将那部分切片。

当我在我的模块中使用此代码片段来设置拦截器时,它不起作用。代码运行没有错误,但没有任何内容被拦截。当我将

String.slice(to_string(__MODULE__), 7..-1) <> ".someFunction/2"
替换为
"SomeModule" <> ".someFunction/2"
时,它确实有效。

我希望有人能指出我在这里做错了什么。

string import elixir interceptor
1个回答
0
投票

首先,人们不会做

String.slice/2
来获取模块名称作为字符串,而是
Kernel.inspect/2

inspect(String)
#⇒ "String"

然后,不手动构建函数捕获,而是使用

Function.capture/3

Function.capture(String, :length, 1) |> inspect  
#⇒"&String.length/1"

最后但同样重要的是,

use/2
__using__/2
的语法糖,它是一个宏,其参数中的远程调用作为 AST 传递给它的实现。但是宏可以从上下文扩展模块参数,这在这种情况下会有所帮助。

就是说,正确的代码应该与以下代码并列。

@config %{
  inspect(Function.capture(__MODULE__, :some_function, 2)) => […]
}
use Interceptor, config: @config

旁注: 我打赌你实际上不需要对捕获进行字符串化。

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