1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
package scala.reflect
/**
* A dynamic proxy which redirects method calls and attribute access to a given
* target object at runtime using reflection.
*
* Usage example:
*
* object x{ def hello = "hello world" }
* val d = new DynamicProxy{ val dynamicProxyTarget = x }
* assert( d.hello == "hello world" )
*
* Not supported (yet):
* - implicit conversions and parameters
* - multiple arguments lists
* - explicit type arguments
*/
trait DynamicProxy extends Dynamic{
/** Method calls on DynamicProxy are redirected to this object. Needs to be defined in a subclass. */
val dynamicProxyTarget : AnyRef
import scala.reflect.mirror._
/**
* boxing to preserve information on primitive types for overloading resolution
*/
case class DynamicReflectBoxed( class_ : Class[_], value: Any )
object DynamicReflectBoxed{
implicit def box[@specialized T]( v:T ) = DynamicReflectBoxed( v.getClass, v )
}
def selectDynamic( method:String ) = {
val symbol = classToType( dynamicProxyTarget.getClass ).member( newTermName(method).encodedName )
invoke( dynamicProxyTarget, symbol )()
}
def updateDynamic( method:String )( value : Any ) = {
val symbol = classToType( dynamicProxyTarget.getClass ).member( newTermName(method+"_=").encodedName )
invoke( dynamicProxyTarget, symbol )( value )
}
def applyDynamic( method:String )( args:DynamicReflectBoxed* ) : Any
= applyDynamicNamed( method )( args.map( value => ("",value) ) :_* )
def applyDynamicNamed( method:String )( args:(String,DynamicReflectBoxed)* ) : Any = {
val class_ = dynamicProxyTarget.getClass
var i = 0
val toolbox = mkToolBox(mkConsoleFrontEnd(),"")
val symbol = classToType( dynamicProxyTarget.getClass ).member( newTermName(method).encodedName )
if(args.size == 0){
invoke( dynamicProxyTarget, symbol )()
} else {
val call =
Apply(
Select(
TypeApply(
Select(
Select(
Ident(newFreeTerm("__this", symbolForName("scala.reflect.DynamicProxy").asType, this))
, newTermName("dynamicProxyTarget")
),
newTermName("asInstanceOf") )
, List(TypeTree().setType(classToType(class_)))
)
,newTermName(method).encodedName
)
,args.map{ case(name,box) =>
val value = Ident(newFreeTerm("__arg"+({i+=1;i}.toString), classToType(box.class_), box.value))
if( name == "" ) value
else AssignOrNamedArg( Ident(name), value )
}.toList
)
toolbox.runExpr( call )
}
}
}
|