2016-12-02 4 views
0
case class Address(address :String ,pinCode : Int)  

case class Person (a: String,b:Int ,c: Address) 

def getClassDefinition[T:TypeTag] = 
    (typeOf[T].members.filter(!_.isMethod).map(r => (r.name -> r.typeSignature))) 

val m = getClassDefinition[Address] 

(pinCode ,scala.Int) 
(address ,String)  

val p =getClassDefinition[Person] 

(c ,A$A332.this.Address) 
(b ,scala.Int) 
(a ,String) 

Ich bin für eine verschachtelte Folge alle Arten und Spaltennamen in verschachteltem Fall Klasse zu erhalten, anstatt nur bis Adresse Fall Klasse geheWie in einer Karte

+1

Also wann genau willst du aufhören? "String" hat auch Member, die keine Methoden sind ... –

+0

Ich möchte, dass es bis zu den benutzerdefinierten Schachtelklassen geht. – Manish

Antwort

1

Wenn ich das Problem zu verstehen, ist es zu bekommen eine Klassendefinition, die ein Name -> Typ-Signatur-Paar für jedes der Nicht-Methoden-Mitglieder des Typs enthält. Wenn die Typ-Signatur ein Standardtyp ist, ist das alles, was benötigt wird; Für einige Typen ist jedoch eine verschachtelte Definition erforderlich. Ich habe dieses entweder/oder Fall mit einem Entweder [Definition, NestedDefinition] modelliert.

In diesem Beispiel habe ich eine isNested-Regel (...) ausgewählt, die mit dem Paketnamen übereinstimmt, aber es könnte eine beliebige Regel sein, die eine Klasse für tiefer gehende Prüfungen identifiziert.

Ich bin mir nicht sicher, ob die Ausgabe in dem von Ihnen erwarteten Format ist, aber Sie können den Beispielcode entweder ändern oder das Ergebnis in Ihre eigene Datenstruktur mappen.

import scala.reflect.runtime.universe._ 

object TypeTags { 
    // Define your domain name here for the isNested(...) test! 
    val myDomainName: String = ??? 

    // Define some type aliases 
    type Definition = ((AnyRef with SymbolApi)#NameType, Type) 
    type EitherDefinitionOrNested = Either[Definition, NestedDefinition] 

    // A nested definition contains the original definition and an iterable collection of its member definitions (recursively). 
    case class NestedDefinition(t: Definition, m: Iterable[EitherDefinitionOrNested]) 

    // The test to determine if a nested definition is needed. 
    def isNested(r: Symbol): Boolean = { 
    r.info.typeSymbol.fullName.startsWith(myDomainName) 
    } 

    // Obtain a class definition from a Symbol. 
    def classDefinition(symbol: Symbol): Iterable[EitherDefinitionOrNested] = { 
    symbol.typeSignature.members.filter(!_.isMethod).map { 
     case r @ nested if isNested(r) => Right(NestedDefinition(nested.name -> nested.typeSignature, classDefinition(nested))) 
     case r       => Left(r.name -> r.typeSignature) 
    } 
    } 

    // Obtain a class definition from a type. 
    def getClassDefinition[T: TypeTag]: Iterable[EitherDefinitionOrNested] = classDefinition(typeOf[T].typeSymbol) 

    // The test case 
    case class Address(address: String ,pinCode: Int) 

    case class Person(a: String, b: Int ,c: Address) 

    def main(args: Array[String]): Unit = { 
    val m = getClassDefinition[Address] 
    val p = getClassDefinition[Person] 

    println(s"address: $m") 
    println(s"person: $p") 
    } 
}