2011-10-20 18 views
7

में ExpandoObject कार्यान्वित करना मैं स्कैला में C#'s 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

कुछ लोगों के आसपास खेलने के बाद यह काम कर रहा है। समाधान हालांकि (typesafe नहीं है जो इस मामले में कोई फर्क नहीं पड़ता, क्योंकि यह छोटे उपयोगिता की बात प्रकार प्रणाली को हल करने के लिए है। :-)

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

मेरे विशेष मामले में, मुझे एक्सेल शीट्स में कुछ संरचित डेटा को संसाधित करना है, जिसे मैं संकलन समय के बारे में कुछ भी नहीं जानता। भाषा स्तर के रिकॉर्ड के रूप में डेटा का इलाज करना आसान प्रसंस्करण करता है। – missingfaktor

+0

आप अधिक उदाहरणों के लिए उपरोक्त लिंक किए गए आलेख को देख सकते हैं। – missingfaktor