简体   繁体   English

如何使用lambda表达式创建“getter”

[英]How to create a 'getter' using a lambda expression

I have an object in use throughout my codebase, UnsecureObject . 我的代码库UnsecureObject有一个正在使用的对象。 This object is auto-generated with no getters/setters, and all member fields are public. 此对象是自动生成的,没有getter / setter,所有成员字段都是公共的。 So editing is done by doing something like the following: 因此,通过执行以下操作完成编辑:

unsecureObjInstance.firstName = "Jane";

This is not desirable for numerous reasons that I probably don't have to explain here. 由于我可能不必在此解释的众多原因,这是不可取的。 But using this generated class is required for some other technical details with our messaging pipeline that I won't go into. 但是使用这个生成的类是我们的消息传递管道的一些其他技术细节所必需的,我不会介绍。

I have a desire is to leverage a mapping utility written by someone else on my team to convert this UnsecureObject to a pojo that I am writing. 我希望利用我团队中其他人编写的映射实用程序将此UnsecureObject转换为我正在编写的pojo。

An example of the mapper in action (with two normal classes w/ getters/setters) would be something like: 运行中的映射器的示例(具有两个具有getter / setter的普通类)将类似于:

new MapperBuilder<>(PojoOne.class, PojoTwo.class)
      .from(PojoOne::getName).to(PojoTwo::getFirstName)
      .build();

This will map the PojoOne#name field to the PojoTwo#firstName field. 这会将PojoOne#name字段映射到PojoTwo#firstName字段。

Is there a way to translate this to input my UnsecureObject here? 有没有办法翻译这个来输入我的UnsecureObject I have tried something like the following: 我尝试过以下内容:

new MapperBuilder<>(UnsecureObject.class, SecureObject.class)
      .from(u -> u.firstName).to(SecureObject::getFirstName)
      .build();

But get an error here, something along the lines of 'u -> u.firstName' could not be invoked. 但是在这里得到一个错误,无法调用'u - > u.firstName'。

So the question is: 所以问题是:

Is there a way to essentially "construct" a getter on the fly using these public members? 有没有办法基本上使用这些公共成员“构建”一个吸气剂? So in the .from() method, I can construct the call to look like a standard method that will yield my u.firstName? 所以在.from()方法中,我可以构造调用看起来像一个标准方法,它将产生我的u.firstName?

Thanks for the help! 谢谢您的帮助!

EDIT: 编辑:

this is approx what the MapperBuilder class looks like (attempted to edit a bit to take away project specific wrappers/simplify) 这大约是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..
  }
}

I dont see MapperBuilder.from() method details, you can try this implementation of MapperBuilder.java Function (getter) -> (BiConsumer) setter 我没看到MapperBuilder.from()方法的详细信息,你可以试试这个MapperBuilder.java Function (getter) -> (BiConsumer) setter实现Function (getter) -> (BiConsumer) setter

public class MapperBuilder<S, D> {

    private final S src;
    private final D dest;

    public MapperBuilder(S src, Class<D> dest) {
        this.src = src;
        try {
            this.dest = dest.newInstance();
        } catch (Exception e) {
            throw new RuntimeException("Required default constructor for: " + dest);
        }
    }

    //getter  - function to get value from source instance
    //setter  - biConsumer to set value to destination instance
    //example - map(SrcClass::getSrcValue, DestClass::setDestValue)
    public <V> MapperBuilder<S, D> map(Function<S, V> getter, BiConsumer<D, V> setter) {
        setter.accept(dest, getter.apply(src));
        return this;
    }

    public D build() {
        return dest;
    }

}

SrcClass.java some source class: SrcClass.java一些源类:

public class SrcClass {

    private String srcValue;

    public String getSrcValue() {
        return srcValue;
    }

    public void setSrcValue(String srcValue) {
        this.srcValue = srcValue;
    }

}

DestClass.java some destination class: DestClass.java一些目标类:

package com.example.demo;

public class DestClass {

    private String destValue;

    public String getDestValue() {
        return destValue;
    }

    public void setDestValue(String destValue) {
        this.destValue = destValue;
    }

}

DemoApplication.java demo: DemoApplication.java演示:

public class DemoApplication {

    public static void main(String[] args) {

        SrcClass src = new SrcClass();
        src.setSrcValue("someValue");

        DestClass dest = new MapperBuilder<>(src, DestClass.class)
                .map(SrcClass::getSrcValue, DestClass::setDestValue)
                // map another fields
                .build();

        // for your UnsecureObject case
        UnsecureObject unsecureObject = new MapperBuilder<>(src, UnsecureObject.class)
                .map(SrcClass::getSrcValue, 
                        (unsecure, srcValue) -> unsecure.unsecureValue = srcValue)
                .build();

    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM