2011-10-20 4 views
7

私はScalaでC#'s ExpandoObjectのようなクラスを実装しようとしています。これは、それが動作するようになっている方法です。ScalaでExpandoObjectを実装する

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を得る:ここで

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

は、私がこれまで試してみましたものです。この仕事を手伝ってください。 :)ありがとう。

答えて

4

周囲を遊んだ後で動作します。ソリューションはタイプセーフではありません(この場合は重要ではありません。この小さなユーティリティのポイントはタイプシステムを回避することです)。

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

使用例を教えてください。 –

+0

私の場合、Excelシートで構造化データを処理する必要があります。コンパイル時には何も分かりません。そのデータを言語レベルのレコードとして扱うと、処理が簡単になります。 – missingfaktor

+0

上記のリンク先の記事を参考にして、より多くの例を参照できます。 – missingfaktor

関連する問題