假设我已经创建了一个可以像这样使用的构建宏
@:build(macros.SampleMacro.build("arg"))
class Main {}
是否可以将其转换为自定义的速记元数据?
@:samplemacro("arg")
class Main {}
关于此的任何文件?
答案 0 :(得分:3)
我不确定是否可行,但您可以利用@:autoBuild()
元数据在接口上工作的事实。这通常用于"标记接口"像这样:
class Main implements ISampleMacro {}
@:autoBuild(macros.SampleMacro.build("arg"))
interface ISampleMacro {}
但是,大概你希望每次使用不同"arg"
,而不是硬编码。您可以使用@:const
类型参数来实现此目的:
class Main implements ISampleMacro<"foo"> {}
@:autoBuild(macros.SampleMacro.build())
interface ISampleMacro<@:const T> {}
在构建宏中提取类型参数的值需要比简单地传递参数更多的努力:
switch (Context.getLocalClass().get().interfaces[0].params[0]) {
case TInst(_.get() => t, params):
switch (t.kind) {
case KExpr({expr: EConst(CString(arg)), pos: _}):
trace(arg); // "foo"
case _:
}
case _:
}
答案 1 :(得分:2)
经过多次磕磕绊绊,我发现有可能做到这一点。
部分解决方案是使用
--macro addGlobalMetadata('$path', '@:build(Build.build())')
这允许您将@:build函数分配给$ path中的所有类。这可以用作编译器选项或haxeflag。
但这本身并不足以采用采用动态参数的元数据标签。但是因为我们现在有一个为所有类执行的Build.build(), Build.build()函数都可以处理检查哪些类具有我们的自定义元数据标签,以及为我们可能需要的类构建任何东西。
要检查我们的自定义元数据标签,我们按如下方式设置检查宏:
class Build {
static var META_STR:String = ":samplemacro";
macro static public function build():Array<Field> {
// We check only those Contexts for where a class type exists
var localClass:Null<Ref<ClassType>> = Context.getLocalClass();
if(localClass == null) return null; // no class type
// We check if the metadata for the class contains our
// custom metadata string at all
if(!localClass.get().meta.has(META_STR)) return null;
// This class does have our custom metadata!
// Because there may be more than one of the same type
// of metadata, we extract a list of all the custom metadata tags
var customTags = localClass.get().meta.extract(META_STR);
// For each tag we can get at the arguments passed in
// by accessing the params field
for(customTag in customTags){
var params = customTag.params;
// Here we can handle each of our @:samplemacro(params) tags,
// save the params for use later, or
// pass the arguments over to another class to deal with
}
var fields = Context.getBuildFields();
// Modify the class fields the way you want
// Optionally destroy the metadata tags afterwards
// with localClass.get().meta.remove(META_STR);
return fields;
}
}
有关addGlobalMetadata的更多详细信息,请访问: https://stackoverflow.com/a/38075492/1502818