2010-10-10 16 views
5

jest możliwe, aby mieć metodę, która pobiera dowolną instancję i zwraca java.reflection.Proxy lub podobne, które ma ten sam typ co oryginalny argument?Dynamic Proxy bez wyraźnego określenia typu w scala

Chyba powinno to wyglądać mniej więcej tak:

def createProxy[S](model: S)(implicit manifest: Manifest[S]): S = {...} 

czy to

def createProxy[S, T<:S](model: S)(implicit manifest: Manifest[S]): T = {...} 

gdzie T jest podtypem S, która wynika z połączenia wszystkich zaimplementowanych interfejsów, ponieważ nie robi Wygląda na to, że mogę Proxy rzeczywiście klasy, ale tylko interfejsy.

+0

trochę stary, ale mimo to ... proxy można obsadzić tylko w interfejsie, a nie w konkretnej klasie. – ozma

Odpowiedz

3

Myślę, że poniższe rozwiązania powinny wystarczyć. Zauważ, że nie może zwrócić S, ponieważ prawdopodobnie S nie jest interfejsem.

import java.lang.reflect._ 

def createProxy[S](model: S)(implicit manifest: Manifest[S]) = { 
    val clazz = manifest.erasure 
    Proxy.newProxyInstance(clazz.getClassLoader, clazz.getInterfaces, new InvocationHandler() { 
    def invoke(proxy:Object, method:Method, args:scala.Array[Object]) = { 
     method.invoke(model, args:_*) 
    } 
    }) 
} 
+0

Typ wyniku to Object, więc nie rozwiązuje mojego problemu. Wygląda na to, że nie mogę mieć tego, czego chcę, więc przyjmuję tę odpowiedź. –

2

W sytuacjach, gdy chcesz pełnomocnika obiektu przy użyciu jednego interfejsu można zrobić coś takiego (w oparciu o Hiram Chirino odpowiedź):

import java.lang.reflect.{Method, InvocationHandler, Proxy} 

def createProxy[I](proxee: I, interfaceClass: Class[I]): I = { 
    assert(interfaceClass.isInterface, "interfaceClass should be an inteface class") 
    Proxy.newProxyInstance(interfaceClass.getClassLoader, Array(interfaceClass), new InvocationHandler() { 
    override def invoke(proxy: Object, method: Method, args: Array[Object]) = { 
     println("before") 
     val result = method.invoke(proxee, args: _*) 
     println("after") 
     result 
    } 
    }).asInstanceOf[I] 
} 

I posiadające interfejs SessionSvc używać go tak jak to :

val sessionSvc = createProxy(new SessionSvcMongo, classOf[SessionSvc]) 

W ten sposób udało mi się wprowadzić raczej bezbolesny AOP do kodu bazującego na wzorach tortów.

Powiązane problemy