vb.net - How do you return an object as the return value through a RealProxy transparent proxy? -
i'm working system plan on using realproxy objects enable intercepting method calls against set of objects, handling call, , returning appropriate results.
this works find simple return types strings or ints, can't seem return objects realproxy.invoke method.
everything works. no errors, returned value nothing, instead of object.
i've worked smallest sample code could, , have included below.
essentially, call rptest , single step through. code creates simple object, rptesta, string field , object valued field retrieves string dim x = c.name works fine , attempts retrieve object
dim r = c.subobj
which returns nothing.
however, in fieldgetter routine, code:
'---- field object type field dim mc = new methodcallmessagewrapper(msg) '---- create object dim o = activator.createinstance(t) '---- , construct return message object dim r = new returnmessage(o, mc.args, mc.args.length, mc.logicalcallcontext, mc) return r
appears work fine, setting returnvalue field of returnmessage object created activator.createinstance(t) call above.
i suspect it's serialization thing of sort, i'm @ loss.
you should able run code straight away, pasting new vb.net project.
'---------------------------------------------------------------------------- imports system.security.permissions imports system.diagnostics imports system.reflection imports system.runtime.compilerservices imports system.runtime.serialization imports system.runtime.remoting imports system.runtime.remoting.activation imports system.runtime.remoting.messaging imports system.runtime.remoting.proxies public module rptest public sub rptest() '---- create new object automatically proxied ' see rpproxyattribute details dim c = new rptesta dim x = c.name 'x returned string value fine dim r = c.subobj '********* problem here, r ends nothing end sub end module 'root test object public class rptesta inherits rpbase public name string = "test name" public subobj rptestb end class 'sub object should returned field value root object above public class rptestb inherits rpbase public subproperty string = "subobj test property" end class ''' <summary> ''' base proxyable object class ''' </summary> ''' <remarks></remarks> <rpproxy()> _ public mustinherit class rpbase inherits contextboundobject end class <permissionset(securityaction.demand, name:="fulltrust")> _ public class rpproxy inherits realproxy private m_target marshalbyrefobject public sub new() m_target = directcast(activator.createinstance(gettype(configrp)), marshalbyrefobject) dim myobjref = remotingservices.marshal(m_target) end sub public sub new(byval classtoproxy type) mybase.new(classtoproxy) end sub public sub new(byval classtoproxy type, byval targetobject marshalbyrefobject) m_target = targetobject dim myobjref = remotingservices.marshal(m_target) end sub public overrides function invoke(byval msg imessage) imessage dim returnmsg imethodreturnmessage = nothing if typeof msg iconstructioncallmessage '---- handle constructor calls dim constructioncallmessage = directcast(msg, iconstructioncallmessage) returnmsg = initializeserverobject(constructioncallmessage) me.m_target = me.getunwrappedserver() setstubdata(me, me.m_target) return returnmsg elseif typeof msg imethodcallmessage '---- handle other method calls dim methodcallmessage = directcast(msg, imethodcallmessage) '---- before message processing preprocess(methodcallmessage) '---- execute method call dim rawreturnmessage = remotingservices.executemessage(me.m_target, methodcallmessage) '---- , postprocess returnmsg = postprocess(methodcallmessage, rawreturnmessage) else throw new notsupportedexception() end if return returnmsg end function 'called before actual method invoked private sub preprocess(byval msg imessage) console.writeline("before method call...") end sub 'called after actual method invoked private function postprocess(byval msg imethodcallmessage, byval msgreturn returnmessage) returnmessage dim r returnmessage if msg.methodname = "fieldgetter" r = fieldgetter(msg, msgreturn) elseif msg.methodname = "fieldsetter" 'na r = msgreturn elseif msg.methodname.startswith("get_") 'na r = msgreturn elseif msg.methodname.startswith("set_") 'na r = msgreturn else r = msgreturn end if return r end function private function fieldgetter(byval msg imethodcallmessage, byval msgreturn imethodreturnmessage) imethodreturnmessage dim t = me.target.gettype '---- retrieves type of field getter should retrieve t = t.getfield(msg.inargs(1), bindingflags.instance or bindingflags.public).fieldtype if t.name = "string" '---- return object returned result of executemessage return msgreturn elseif t.basetype.equals(gettype(rpbase)) '---- field object type field dim mc = new methodcallmessagewrapper(msg) '---- create object dim o = activator.createinstance(t) '---- , construct return message object dim r = new returnmessage(o, mc.args, mc.args.length, mc.logicalcallcontext, mc) return r else return msgreturn end if end function public property target() object return me.m_target end set(byval value object) me.m_target = value end set end property end class <attributeusage(attributetargets.class)> _ <securitypermissionattribute(securityaction.demand, flags:=securitypermissionflag.infrastructure)> _ public class rpproxyattribute inherits proxyattribute public overrides function createinstance(byval type type) marshalbyrefobject dim proxy = new rpproxy(type) dim transparentproxy = directcast(proxy.gettransparentproxy(), marshalbyrefobject) return transparentproxy end function end class
well, turns out pretty simple fix, once work past god awful returnmessage constructor that's quite misleading!
many old colleague of mine, rich quackenbush, taking few minutes , checking out. sometimes, can't see forest trees!
anyway, in fieldgetter, doing this
elseif t.basetype.equals(gettype(rpbase)) '---- field object type field dim mc = new methodcallmessagewrapper(msg) '---- create object dim o = activator.createinstance(t) '---- , construct return message object dim r = new returnmessage(o, mc.args, mc.args.length, mc.logicalcallcontext, mc) return r
seems reasonable, newly created object being passed returnmessage constructor argument called returnvalue.
but no. have create object array , pass 3 element in array, this:
elseif t.basetype.equals(gettype(rpbase)) '---- field object type field dim mc = new methodcallmessagewrapper(msg) '---- create object dim o = activator.createinstance(t) '---- , construct return message object dim r = new returnmessage(nothing, new object() {nothing, nothing, o}, 3, mc.logicalcallcontext, mc) return r
it turns out, because fieldgetter function in being "called" , intercepted proxy, , it's signature is
fieldgetter(stringtypename,stringfieldname,object&val)
which, purposes of constructing returnmessage call means doesn't have returnvalue @ all, rather return value returned 3'rd argument in list.
since i'm not calling real fieldgetter function, first 2 argument (the typename , fieldname) immaterial, 3'rd argument proper place put return value.
it's obvious in hindsight!
many rich.
Comments
Post a Comment