将函数参数列表的字符串表示形式转换为实际参数,以进行反射调用



更新:在得到一个意想不到的好答案后,我在这个问题的底部添加了一些上下文,准确地说明了我将如何使用这些字符串函数调用

我需要翻译字符串,例如
my.package.ClassName#functionName(1, "a string value", true)

转换为对该函数的反射调用。获取包、类和函数名不是问题。我已经开始使用自己的解决方案来解析参数列表,确定每个参数的类型并返回一个适当的对象。

(我将类型的范围限制为八个原语加上字符串。null将被认为是一个字符串,逗号和双引号必须用一些简单的标记严格转义,例如__DBL_QT__,以避免在逗号上进行不转义和分割的复杂性。

我不是在问如何通过字符串解析做到这一点,因为我知道如何。只是需要做很多工作,我希望已经有解决方案了。不幸的是,它是如此通用的术语,我找不到任何地方。

我理解要求外部现有库是离题的。我只是希望在它关闭之前得到一些反馈,甚至是一个更好的搜索条件的建议。或者,可能会提出一种完全不同的方法……

谢谢。


背景:

每个函数调用都在函数的JavaDoc块中找到,并且表示一段示例代码——它的源代码或它的System.out输出——将显示在该位置。

参数用于自定义其显示,如

  • 缩进,
  • 删除不相关的部分(如许可块),和
  • 用于javadoc -链接最重要的函数。此自定义主要用于源代码表示,但也可以应用于其输出。

(第一个参数始终是Appendable,它将执行实际输出。)

用户需要能够调用任何函数,在许多情况下,该函数将是位于JavaDoc-ed函数本身下面的私有静态函数。

我编写的应用程序将读取源代码文件(包含JavaDoc块的文件,其中存在这些字符串函数调用),并创建*.java文件的副本,该文件随后将由javadoc处理。

因此,对于每一段示例代码,可能会有两个,甚至更多的字符串函数调用。可能还有更多,因为我可能想要在不同的上下文中显示同一个示例的不同片段——可能是在整个类JavaDoc块中显示整个示例,并在该类的相关函数中显示它的片段。

我已经编写了解析源代码的过程(源代码包含JavaDoc块,它与读取示例代码的过程是分开的),并使用insert example-code hereinsert example-code-output here标记盲目地重新输出其源代码。

我现在在InsertExampleCode对象中有这个字符串函数调用,在字符串字段中。现在我需要按照问题开头的描述来做。找出他们想要调用的函数,然后这样做。

#更改为点(.),围绕它编写一个类定义,以便您有一个有效的Java源文件,在类路径中包含tools.jar并调用com.sun.tools.javac.Main

创建您自己的ClassLoader实例来加载编译后的类,并运行它(使它实现一个有用的接口,例如java.util.concurrent.Callable,以便您可以轻松获得调用的结果)

我为此创建的名为com.github.aliteralmind.codelet.simplesig.SimpleMethodSignature的类是一个重要的Codelet,用于翻译每个标记的"customizer"部分,这是一个自定义标记输出的函数。

(安装说明。类路径中必须包含的jar文件只有codelet和xbnjava。)

示例字符串签名,在标签中:

{@.codelet.and.out com.github.aliteralmind.codelet.examples.adder.AdderDemo%eliminateCommentBlocksAndPackageDecl()}

定制器部分是百分号(%)之后的所有内容。此自定义器仅包含函数名和空参数。这意味着该函数必须存在于少数严格指定的类集中。

{@.codelet.and.out com.github.aliteralmind.codelet.examples.adder.AdderDemo%lineRange(1, false, "Adder adder", 2, false, "println(adder.getSum())", "^ ")}

这也指定了参数,按照设计,这些参数是"简单的"——要么是非空字符串,要么是基本类型。

{@.codelet.and.out com.github.aliteralmind.codelet.examples.adder.AdderDemo%com.github.aliteralmind.codelet.examples.LineRangeWithLinksCompact#adderDemo_lineSnippetWithLinks()}

指定函数所在的显式包和类。


由于这些标签的性质以及字符串签名的实现方式,我决定坚持使用直接字符串解析而不是动态编译。

使用SimpleMethodSignature的两个例子:

在第一个例子中,完整的签名(包、类和函数名,包括它的所有参数)都在字符串中指定。

   import  com.github.aliteralmind.codelet.simplesig.SimpleMethodSignature;
   import  com.github.xbn.lang.reflect.InvokeMethodWithRtx;
   import  java.lang.reflect.Method;
public class SimpleMethodSigNoDefaults  {
   public static final void main(String[] ignored)  {
      String strSig = "com.github.aliteralmind.codelet.examples.simplesig." +
         "SimpleMethodSigNoDefaults#getStringForBoolInt(false, 3)";
      SimpleMethodSignature simpleSig = null;
      try  {
         simpleSig = SimpleMethodSignature.newFromStringAndDefaults(
            String.class, strSig, null, null,
            null);         //debug (on=System.out, off=null)
      }  catch(ClassNotFoundException cnfx)  {
         throw  new RuntimeException(cnfx);
      }
      Method m = null;
      try  {
         m = simpleSig.getMethod();
      }  catch(NoSuchMethodException nsmx)  {
         throw  new RuntimeException(nsmx);
      }
      m.setAccessible(true);
      Object returnValue = new InvokeMethodWithRtx(m).sstatic().
         parameters(simpleSig.getParamValueObjectList().toArray()).invokeGetReturnValue();
      System.out.println(returnValue);
   }
   public static final String getStringForBoolInt(Boolean b, Integer i)  {
      return  "b=" + b + ", i=" + i;
   }
}
输出:

b=false, i=3

第二个示例演示了未指定(包和)类名的字符串签名。直接提供类,其中必须存在函数

   import  com.github.aliteralmind.codelet.simplesig.SimpleMethodSignature;
   import  com.github.xbn.lang.reflect.InvokeMethodWithRtx;
   import  java.lang.reflect.Method;
public class SimpleMethodSigWithClassDefaults  {
   public static final void main(String[] ignored)  {
      String strSig = "getStringForBoolInt(false, 3)";
      SimpleMethodSignature simpleSig = null;
      try  {
         simpleSig = SimpleMethodSignature.newFromStringAndDefaults(
            String.class, strSig, null,
            new Class[]{Object.class, SimpleMethodSigWithClassDefaults.class, SimpleMethodSignature.class},
            null);         //debug (on=System.out, off=null)
      }  catch(ClassNotFoundException cnfx)  {
         throw  new RuntimeException(cnfx);
      }
      Method m = null;
      try  {
         m = simpleSig.getMethod();
      }  catch(NoSuchMethodException nsmx)  {
         throw  new RuntimeException(nsmx);
      }
      m.setAccessible(true);
      Object returnValue = new InvokeMethodWithRtx(m).sstatic().
         parameters(simpleSig.getParamValueObjectList().toArray()).invokeGetReturnValue();
      System.out.println(returnValue);
   }
   public static final String getStringForBoolInt(Boolean b, Integer i)  {
      return  "b=" + b + ", i=" + i;
   }
}
输出:

b=false, i=3

相关内容

  • 没有找到相关文章

最新更新