2013-04-18 28 views
25

Làm thế nào tôi có thể trích xuất các giá trị trường từ một trường hợp lớp trong scala bằng cách sử dụng mô hình phản ánh mới trong scala 2.10? Ví dụ, bằng cách sử dụng dưới đây không kéo ra các phương pháp lĩnh vựcScala 2,10 phản ánh, làm thế nào để trích xuất các giá trị trường từ một trường hợp lớp

def getMethods[T:TypeTag](t:T) = typeOf[T].members.collect { 
    case m:MethodSymbol => m 
    } 

tôi có kế hoạch bơm chúng vào

for {field <- fields} { 
    currentMirror.reflect(caseClass).reflectField(field).get 
    } 

Trả lời

39

MethodSymbol có một phương pháp isCaseAccessor cho phép bạn làm một cách chính xác này:

def getMethods[T: TypeTag] = typeOf[T].members.collect { 
    case m: MethodSymbol if m.isCaseAccessor => m 
}.toList 

Bây giờ bạn có thể viết như sau:

scala> case class Person(name: String, age: Int) 
defined class Person 

scala> getMethods[Person] 
res1: List[reflect.runtime.universe.MethodSymbol] = List(value age, value name) 

Và bạn chỉ nhận được các ký hiệu phương thức bạn muốn.

+0

Ah tôi nhận ra rằng cách tiếp cận của tôi đã sai. Bất kỳ ý tưởng làm thế nào để có được caseAccessors từ một lớp trường hợp không rõ? Trình duyệt IE hiện được lưu trữ dưới dạng val SomeCaseClass: Bất kỳ –

+0

Chờ, không có nó currentMirror.reflect (someCaseClass) .symbol.asType.typeSignature.members –

+0

Có thể làm việc với môi trường đa luồng dưới scala 2.10 không? – jilen

10

Nếu bạn muốn có được fancier, bạn có thể nhận được chúng theo thứ tự bằng cách kiểm tra biểu tượng hàm tạo. Mã này hoạt động ngay cả khi loại lớp trong câu hỏi có nhiều hàm tạo được định nghĩa.

import scala.collection.immutable.ListMap 
    import scala.reflect.runtime.universe._ 

    /** 
    * Returns a map from formal parameter names to types, containing one 
    * mapping for each constructor argument. The resulting map (a ListMap) 
    * preserves the order of the primary constructor's parameter list. 
    */ 
    def caseClassParamsOf[T: TypeTag]: ListMap[String, Type] = { 
    val tpe = typeOf[T] 
    val constructorSymbol = tpe.decl(termNames.CONSTRUCTOR) 
    val defaultConstructor = 
     if (constructorSymbol.isMethod) constructorSymbol.asMethod 
     else { 
     val ctors = constructorSymbol.asTerm.alternatives 
     ctors.map(_.asMethod).find(_.isPrimaryConstructor).get 
     } 

    ListMap[String, Type]() ++ defaultConstructor.paramLists.reduceLeft(_ ++ _).map { 
     sym => sym.name.toString -> tpe.member(sym.name).asMethod.returnType 
    } 
    } 
+0

Tôi đang tìm các trường hợp không thành công với 'scala.ScalaReflectionException: không phải là một thuật ngữ' trong biểu thức' constructorSymbol.asTerm.alternatives'. Các bình luận tài liệu cho 'khai báo' đề cập đến' OverloadedSymbol', nhưng không có thực thể như vậy dường như tồn tại. –

+0

Nó chỉ ra rằng điều đó đã xảy ra bởi vì tôi đã gọi nó với 'this.type' từ một đặc điểm được sử dụng như một siêu kiểu của lớp vỏ trong câu hỏi. –

+0

Ngoài ra, 'trường hợp lớp P (i: Int) (j: Int)'. –