2011-10-20 26 views
7

Tôi đang cố triển khai lớp học C#'s ExpandoObject giống như ở Scala. Đây là cách nó là vụ phải làm việc:Triển khai ExpandoObject trong Scala

val e = new ExpandoObject 
e.name := "Rahul" // This inserts a new field `name` in the object. 
println(e.name) // Accessing its value. 

Dưới đây là những gì tôi đã cố gắng cho đến nay:

implicit def enrichAny[A](underlying: A) = new EnrichedAny(underlying) 
class EnrichedAny[A](underlying: A) { 
    // ... 
    def dyn = new Dyn(underlying.asInstanceOf[AnyRef]) 
} 

class Dyn(x: AnyRef) extends Dynamic { 
    def applyDynamic(message: String)(args: Any*) = { 
    new Dyn(x.getClass.getMethod(message, 
     args.map(_.asInstanceOf[AnyRef].getClass) : _*). 
     invoke(x, args.map(_.asInstanceOf[AnyRef]) : _*)) 
    } 
    def typed[A] = x.asInstanceOf[A] 
    override def toString = "Dynamic(" + x + ")" 
} 

class ExpandoObject extends Dynamic { 
    private val fields = mutable.Map.empty[String, Dyn] 
    def applyDynamic(message: String)(args: Any*): Dynamic = { 
    fields get message match { 
     case Some(v) => v 
     case None => new Assigner(fields, message).dyn 
    } 
    } 
} 

class Assigner(fields: mutable.Map[String, Dyn], message: String) { 
    def :=(value: Any): Unit = { 
    fields += (message -> value.dyn) 
    } 
} 

Khi tôi cố gắng để biên dịch mã này, tôi nhận được một StackOverflowError. Xin hãy giúp tôi làm việc này. :) Cảm ơn.

Trả lời

4

Làm việc sau khi một số người chơi xung quanh. Các giải pháp không phải là an toàn mặc dù (trong trường hợp này không quan trọng, vì điểm của tiện ích nhỏ này là làm việc xung quanh hệ thống kiểu. :-)

trait ExpandoObject extends Dynamic with mutable.Map[String, Any] { 
    lazy val fields = mutable.Map.empty[String, Any] 
    def -=(k: String): this.type = { fields -= k; this } 
    def +=(f: (String, Any)): this.type = { fields += f; this } 
    def iterator = fields.iterator 
    def get(k: String): Option[Any] = fields get k 
    def applyDynamic(message: String)(args: Any*): Any = { 
    this.getOrElse(message, new Assigner(this, message)) 
    } 
} 

implicit def anyToassigner(a: Any): Assigner = a match { 
    case x: Assigner => x 
    case _ => sys.error("Not an assigner.") 
} 

class Assigner(ob: ExpandoObject, message: String) { 
    def :=(value: Any): Unit = ob += (message -> value) 
} 
+0

Bạn có thể đưa ra ví dụ sử dụng không? –

+0

Trong trường hợp cụ thể của tôi, tôi phải xử lý một số dữ liệu có cấu trúc trong các trang tính Excel mà tôi không biết gì về thời gian biên dịch. Việc xử lý dữ liệu đó dưới dạng bản ghi cấp độ ngôn ngữ giúp việc xử lý đơn giản hơn. – missingfaktor

+0

Bạn có thể tham khảo bài viết được liên kết ở trên để biết thêm ví dụ. – missingfaktor

Các vấn đề liên quan