Implementing ExpandoObject in Scala

I am trying to implement C#'s ExpandoObject -like class in Scala. This is how it is supposed to work:

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

Here is what I have tried so far:

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)
  }
}

When I try to compile this code, I get a StackOverflowError . Please help me get this work. :) Thanks.


Got it working after some playing around. The solution isn't typesafe though (which in this case does not matter, since the point of this little utility is to work around type system. :-)

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)
}
链接地址: http://www.djcxy.com/p/55766.html

上一篇: 如何将一个苹果代表添加到水果代表列表中?

下一篇: 在Scala中实现ExpandoObject