【问题标题】:Implementing ExpandoObject in Scala在 Scala 中实现 ExpandoObject
【发布时间】:2011-10-20 07:19:19
【问题描述】:

我正在尝试在 Scala 中实现 C#'s ExpandoObject-like 类。它应该是这样工作的:

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

这是我迄今为止尝试过的:

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

当我尝试编译这段代码时,我得到一个StackOverflowError。请帮我完成这项工作。 :) 谢谢。

【问题讨论】:

    标签: c# scala dynamic expandoobject


    【解决方案1】:

    玩了一会儿就搞定了。该解决方案虽然不是类型安全的(在这种情况下并不重要,因为这个小实用程序的目的是解决类型系统。:-)

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

    【讨论】:

    • 你能举个使用例子吗?
    • 在我的特殊情况下,我必须在 Excel 工作表中处理一些结构化数据,而我在编译时对此一无所知。将这些数据视为语言级别的记录可以简化处理。
    • 您可以参考上面的链接文章以获取更多示例。
    猜你喜欢
    • 1970-01-01
    • 2011-06-07
    • 2011-07-18
    • 2014-10-26
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多