如何在第一个 MethodCall 的第一个参数上调用一个 MethodCall 和另一个 MethodCall?

How do I invoke a MethodCall with another MethodCall on the first MethodCall's first argument?

我正在尝试实现这个:

@Override // java.util.Function
public Object apply(final ThingWithParameters thing) {
  return bozo(thing.getParameters());
}
private Object bozo(final Object[] parameters) {
  // Use magic ByteBuddy stuff to "spread" the parameters out
  return this.object.baz(parameter0, parameter1); // ...where these are the first two parameters in the array
}

我试过:

builder = builder
  .defineMethod("bozo" ...)
  .implement(MethodCall.invoke(bazDescription)
             .onField(thisObjectFieldDescription)
             .withArgumentArrayElements(0, 2))

  .implement(parameterizedTypeFunctionThingWithParametersObject) // Function<ThingWithParameters, Object>
  .intercept(MethodCall.invoke(bozoDescription) // implement apply(ThingWithParameters thing): call bozo()...
             .withMethodCall(MethodCall.invoke(getParametersMethodDescription) // ...with the result of invoking getParameters()...
                             .onArgument(0))); // ...on thing (except see below)

…但这行不通。错误消息非常奇怪,让我相信参数 0 不是指 thing,而是指完全不同的东西(也许接收者类型不知何故?)。这是堆栈中的一个片段:

java.lang.IllegalStateException: Cannot invoke public java.lang.Object[] com.foo.ThingWithParameters.getParameters() on java.util.function.Function<? super V, ? extends com.foo.ThingWithParameters>
    at net.bytebuddy.implementation.MethodCall$TargetHandler$ForMethodParameter$Resolved.toStackManipulation(MethodCall.java:2530)
    at net.bytebuddy.implementation.MethodCall$Appender.toStackManipulation(MethodCall.java:3548)
    at net.bytebuddy.implementation.MethodCall$ArgumentLoader$ForMethodCall.toStackManipulation(MethodCall.java:1687)
    at net.bytebuddy.implementation.MethodCall$Appender.toStackManipulation(MethodCall.java:3545)
    at net.bytebuddy.implementation.MethodCall$Appender.apply(MethodCall.java:3509)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyCode(TypeWriter.java:708)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod$WithBody.applyBody(TypeWriter.java:693)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$MethodPool$Record$ForDefinedMethod.apply(TypeWriter.java:600)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default$ForCreation.create(TypeWriter.java:5660)
    at net.bytebuddy.dynamic.scaffold.TypeWriter$Default.make(TypeWriter.java:2166)
    at net.bytebuddy.dynamic.scaffold.subclass.SubclassDynamicTypeBuilder.make(SubclassDynamicTypeBuilder.java:232)

请注意,虽然我的代理 class 实际上实现了 Function,但它实际上实现了 Function<ThingWithParameters, Object>。而且,我从不定义 V。我假设 ByteBuddy 在内部某处执行此操作。

我应该使用什么食谱?

Function class 定义了多种方法,其中一些是默认方法。 Byte Buddy 将尝试通过您的 Implementation 实现所有这些方法,其中它适用于 apply 方法,但对其他方法无效。因此,不如定义一个显式匹配器来指示您要实现的方法。