在 Orika 中定义映射时真的可以使用泛型吗?

Is it actually possible to use generics when defining mappings in Orika?

我知道那种类型擦除,并且会在定义映射时阻止使用泛型,正如这个问题指出的那样 how to map generics objects with Orika?. But Orika FAQ,在 Are generics supported 部分,claims :

Yes. Orika includes special runtime support for the mapping of generic types via a special Type class which can be used to define the exact type elements of a templated type.

理想情况下,像下面这样的东西应该可以工作(假设我们可以通过一些 Orika 功能在运行时以某种方式维护 class 参数):

     mapperFactory.classMap(Asset<T,K>.class, AssetDto<K>.class)
    .maybeSomeCustomization...
    .byDefault()
    .register();

我找不到关于 Orika FAQ 提到的 Type<?> class 用法的任何示例。

有可能,你需要使用MapperFactory#classMap(Type<A>, Type<B>) API而不是MapperFactory#classMap(Class<A>, Class<B>)

您可以在 generics 包中找到 Orika 测试中的大量示例。

要构造一个 Type 实例,您可以使用 TypeBuilder:

的就地匿名子类
Type<MyGenericClass<GenericParam1, GenericParam2>> type =
    new TypeBuilder<MyGenericClass<GenericParam1, GenericParam2>>() {}.build();

注意创建匿名子类的构造函数后的方括号{}。这样 Orika 就可以使用 ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments().

找到实际的 MyGenericClass<GenericParam1, GenericParam2> 类型参数

您可以使用 TypeBuilder API 来保留通用类型信息,以便 Orika 在执行映射时可以使用它。

请注意 Java 不允许我们在 Class 文字中指定类型参数。例如,我们不能写Asset<Book>.class。此外,由于类型擦除,我们无法在运行时访问实际的类型参数。简而言之,原始类型 - 即 Asset.class - 没有向 Orika 提供足够的信息。

所以首先,我们必须使用 TypeBuilder:

创建通用类型
Type<Asset<Person>> sourceType = new TypeBuilder<Asset<Person>>() {}.build();
Type<AssetDto<Person>> targetType = new TypeBuilder<AssetDto<Person>>(){}.build();

然后在classMap调用中,我们必须使用这些类型:

factory.classMap(sourceType, targetType).byDefault().register();

最后,我们可以使用这些类型执行映射:

factory.getMapperFacade().map(asset, sourceType, targetType);

阅读以下post以获得generics usage with Orika的详细解释。