Re: how can i reflect the instantiated return type of a generic type's method?

Daniel Armak <[email protected]> Sat, 12 Mar 2016 19:12:58 +0200
Newsgroups gmane.comp.lang.scala
Message-ID <CADtYB+m9zSVBo6HtT5BFM2GQmSZ6VO1j9ffNAUi-6CcZoLVi2g@mail.gmail.com>
BTW Leon, please submit usage questions to the scala-user mailing list.
scala-language is for discussing the language itself.

Daniel Armak

On Sat, Mar 12, 2016 at 6:47 PM, Daniel Armak <[email protected]> wrote:

> You need to use Symbol.typeSignatureIn(Type):
>
> scala> case class Person[T](name: T)
> defined class Person
>
> scala> val tpe = typeOf[Person[String]]
> tpe: reflect.runtime.universe.Type = Person[String]
>
> scala> val method = tpe.members.find(_.name.toString == "name").get.asMethod
> method: reflect.runtime.universe.MethodSymbol = value name
>
> scala> val methodType = method.typeSignatureIn(tpe)
> methodType: reflect.runtime.universe.Type = => String
>
> scala> methodType.resultType
> res24: reflect.runtime.universe.Type = String
>
> ​
>
> Daniel Armak
>
> On Mon, Mar 7, 2016 at 11:09 AM, Leon <[email protected]> wrote:
>
>> Hi,
>>
>> I have just write a method to reflect the methods of case class, but meet
>> some problem, the code is:
>>
>>
>>     case class Name(first: String, last: String)
>>     case class Person[T](name: T, age: Int)
>>     case class America(val name: Name, val age: Int)
>>
>>     val m = runtimeMirror(getClass.getClassLoader)
>>
>>     def getFlattenFields(tag: Type, prefix: String = ""): Map[String,
>> Method] = {
>>         val cls = m.runtimeClass(tag)
>>         tag.members.filter(sym =>
>>             sym.isMethod && sym.asMethod.isGetter && sym.asMethod.isPublic
>>         ).flatMap { sym =>
>>             val methodSym = sym.asMethod
>>             val returnType = methodSym.returnType
>> *            // When reflect generic types, the returnType will be
>> something like 'T' but not the*
>> *            // instantiated return type, how can i get the real return
>> type instead of the generic*
>> *            // type ?*
>>             Map[String, Method](prefix + methodSym.name.toString ->
>>                 cls.getDeclaredMethod(methodSym.name.toString)) ++
>>                 (if (returnType.typeSymbol.isClass &&
>> returnType.typeSymbol.asClass.isCaseClass) {
>>                     getFlattenFields(returnType, prefix +
>> methodSym.name.toString + ".")
>>                 } else {
>>                     Map.empty[String, Method]
>>                 })
>>         } toMap
>>     }
>>
>>     println(getFlattenFields(typeOf[Person[Name]]))
>>     println(getFlattenFields(typeOf[America]))
>>
>>
>> the result of above is:
>>
>> Map(age -> public int test.Reflect$Person.age(), name -> public
>> java.lang.Object test.Reflect$Person.name())
>> Map(age -> public int test.Reflect$America.age(), name -> public
>> test.Reflect$Name test.Reflect$America.name(), name.last -> public
>> java.lang.String test.Reflect$Name.last(), name.first -> public
>> java.lang.String test.Reflect$Name.first())
>>
>> the first line of the result is not my expectation, how can i get the
>> second line, but using "println(getFlattenFields(typeOf[Person[Name]]))"?
>>
>>
>> Thanks very much
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "scala-language" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>

-- 
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
For more options, visit https://groups.google.com/d/optout.