Я использую Java, чтобы изменить какой-то классный код, используя отражение.
Оригинальный заводной код в форме:
void method() {
A(processId);
B();
}
Мне нужно изменить это, чтобы добавить processId:
void callMethod() {
int processId = rand();
invokeMethod(
{->
A(processId);
B();
}, processId);
}
void invokeMethod(Closure closure, int processId) {
doSomething(processId);
closure.call();
}
Примечание: invokeMethod () является существующим методом и не внедряется.
Когда я изменил исходный код, как указано выше, я получаю эту ошибку:
"groovy.lang.MissingPropertyException: нет такого свойства: processId"
Я пытался установить переменнуюScope метода "callMethod", чтобы включить переменную "processId" в качестве DeclaredVariable.
Для справки, вот код, который я использовал для этого:
private void wrapMethod(@NonNull MethodNode node)
{
VariableExpression var = new VariableExpression("processId", new ClassNode(Integer.class));
var.setClosureSharedVariable(true);
//Generate a statement that creates a processId
Statement statement = GeneralUtils.declS(var, GeneralUtils.callThisX("getUUID"));
ClosureExpression methodClosure = createMethodClosure(node);
ArgumentListExpression args = createArgumentListExpression(methodClosure,
varX("processId"));
MethodCallExpression method = GeneralUtils.callThisX("invokeMethod", args);
BlockStatement newMethodCode = GeneralUtils.block(statement, GeneralUtils.stmt(method));
newMethodCode.setVariableScope(methodClosure.getVariableScope().copy());
//Just to be safe, modifying the scope of the node as well.
VariableScope newScope = node.getVariableScope().copy();
newScope.putDeclaredVariable(var);
node.setCode(newMethodCode);
node.setVariableScope(newScope);
}
private ClosureExpression createMethodClosure(MethodNode node) {
//Get code from within node to dump into a closure.
BlockStatement block = (BlockStatement) node.getCode();
//Setting closureScope and adding processId
VariableScope closureScope = block.getVariableScope().copy();
closureScope.getReferencedLocalVariablesIterator()
.forEachRemaining(x -> x.setClosureSharedVariable(true));
Variable var = new VariableExpression("processId", new ClassNode(Integer.class));
var.setClosureSharedVariable(true);
closureScope.putDeclaredVariable(var);
ClosureExpression methodClosure = GeneralUtils.closureX(block);
methodClosure.setVariableScope(closureScope);
return methodClosure;
}
Я проверил код, чтобы проверить, что 'processId' доступен в блоке invokeMethod () и что результирующий код из внедрения такой же, как и ожидалось.
Есть идеи, почему это не работает?