raphw / byte-buddy

Runtime code generation for the Java virtual machine.
https://bytebuddy.net
Apache License 2.0
6.23k stars 804 forks source link

How to generate multi-level generic code ? #1649

Closed mxsky closed 4 months ago

mxsky commented 4 months ago

// The following code is correct >>> Result TypeDescription.Generic resultClass = TypeDescription.Generic.Builder.parameterizedType(Result.class, List.class).build();

// but how to get Result<List> ?
// DictData is a dynamic class, I have a declaring class :Result { ... } ----> TypeDescription.Generic listGeneric = TypeDescription.Generic.Builder.parameterizedType(List.class, rowClass).build(); ----> TypeDescription.Generic build = TypeDescription.Generic.Builder.rawType(Result.class, listGeneric).build(); ------> error tip : Result does not have a declaring type: java.util.List

I've tried, but there's nothing I can do. Teach me ...

raphw commented 4 months ago

How do your type definitions look like? List is in itself generic. Should it not be the other way round?

mxsky commented 4 months ago

I already solved it yesterday, but thank you for your answer !

public static DynamicType.Builder addListMethod(Class clazz, String code, Class entityClass, Class queryClass, Class rowClass){
    AnnotationDescription apiAnn = AnnotationDescription.Builder.ofType(ApiOperation.class).define("value", "列表查询").build();
    AnnotationDescription mappingAnn = AnnotationDescription.Builder.ofType(GetMapping.class).defineArray("value", "/list/"+code).build();

    //构造:List<V>
    TypeDefinition listType = TypeDescription.Generic.Builder.parameterizedType(List.class, rowClass).build();
    // >>>>>listType = java.util.List<com.demo.dto.DictDataVO>
    log.debug(">>>>>listType = {}", listType.getActualName());

    //构造:Result<List<V>>
    TypeDescription resultType = TypeDescription.ForLoadedType.of(Result.class);
    TypeDefinition resultClass = TypeDescription.Generic.Builder.parameterizedType(resultType, listType).build();
    // >>>>>resultClass = com.demo.Result<java.util.List<com.demo.DictDataVO>>
    log.debug(">>>>>resultClass = {}", resultClass.getActualName());

    //生成代码 public Result<List<DictDataVO>> list(DictDataQuery example) { ... }
    DynamicType.Builder redefine = new ByteBuddy().redefine(clazz);
    redefine = redefine.defineMethod("list", resultClass, Visibility.PUBLIC)
            .withParameter(queryClass, "example")
            .intercept(MethodDelegation.to(new DelegationMiniApi(code, entityClass)))
            .annotateType(apiAnn)
            .annotateType(mappingAnn);
    return redefine;
}