У меня есть объект, используемый во всей моей кодовой базе, UnsecureObject
.Этот объект создается автоматически без методов получения / установки, и все поля-члены являются открытыми.Поэтому редактирование выполняется следующим образом:
unsecureObjInstance.firstName = "Jane";
Это нежелательно по многим причинам, которые мне, вероятно, здесь объяснять не нужно.Но использование этого сгенерированного класса требуется для некоторых других технических деталей с нашим конвейером обмена сообщениями, в которые я не буду вдаваться.
У меня есть желание использовать картографическую утилиту, написанную кем-то из моей команды, чтобы преобразовать это UnsecureObject
в pojo, которое я пишу.
Пример маппера в действии (с двумя обычными классами w / getters / setters) будет выглядеть примерно так:
new MapperBuilder<>(PojoOne.class, PojoTwo.class)
.from(PojoOne::getName).to(PojoTwo::getFirstName)
.build();
Это сопоставит поле имени PojoOne # с PojoTwo #поле firstName.
Есть ли способ перевести это для ввода моего UnsecureObject
здесь?Я пробовал что-то вроде следующего:
new MapperBuilder<>(UnsecureObject.class, SecureObject.class)
.from(u -> u.firstName).to(SecureObject::getFirstName)
.build();
Но получите ошибку здесь, что-то вроде 'u -> u.firstName' не может быть вызвано.
Итак, вопрос в следующем:
Есть ли способ по существу "создать" геттер на лету, используя этих открытых членов?Таким образом, в методе .from () я могу создать вызов, похожий на стандартный метод, который даст мой u.firstName?
Спасибо за помощь!
РЕДАКТИРОВАТЬ:
это примерно то, как выглядит класс MapperBuilder (попытка немного отредактировать, чтобы убрать специфичные для проекта оболочки / упростить)
/**
* This class is used to convert between POJO getter method references to the corresponding field names.
* @param <B> type
*/
public interface PojoProxy<B> {
/**
* Invokes the given getter method and returns information about the invocation.
* @param getter the getter to invoke
* @return information about the method invoked
*/
<T> GetterInvocation<T> invokeGetter(Function<B, T> getter);
}
/**
* Stores information about a method invocation.
* @param <T> method return type
*/
public interface GetterInvocation<T> {
public Class<T> getReturnType();
public String getFieldName();
}
/**
* A builder class to create {@link Mapper} instances.
* @param <FROM> source type
* @param <TO> target type
*/
public class MapperBuilder<FROM, TO> {
private final Class<FROM> _fromClass;
private final Class<TO> _toClass;
private final PojoProxy<FROM> _fromProxy;
private final PojoProxy<TO> _toProxy;
public MapperBuilder(Class<FROM> fromClass, Class<TO> toClass) {
_fromClass = fromClass;
_toClass = toClass;
//We will pretend there is an impl that provides the proxy.
//Proxies wrap the from and to classes in order to get reflection information about their getter calls.
_fromProxy = PojoProxy.of(fromClass);
_toProxy = PojoProxy.of(toClass);
}
public <FROM_VALUE> ToFieldBuilder<FROM_VALUE> from(Function<FROM, FROM_VALUE> getter) {
GetterInvocation<FROM_VALUE> methodInvocation = _fromProxy.invokeGetter(getter);
return new ToFieldBuilder<>(methodInvocation.getFieldName(), methodInvocation.getReturnType());
}
public class ToFieldBuilder<FROM_VALUE> {
private final String _fromFieldPath;
private final Class<FROM_VALUE> _fromClass;
public ToFieldBuilder(String fromFieldPath, Class<FROM_VALUE> fromClass) {
_fromFieldPath = fromFieldPath;
_fromClass = fromClass;
}
public <TO_VALUE> FromFieldBuilder<FROM_VALUE, TO_VALUE> to(Function<TO, TO_VALUE> getter) {
//similar to above, but now using a FromFieldBuilder.
}
}
public class FromFieldBuilder<FROM_VALUE, TO_VALUE> {
//impl..
}
}