Alternatives to RealProxy

M

Myren

I'm wondering what alternatives, if any, there are to realproxy for
intercepting methods on objects. I'm trying to create code which can at
run time change what methods do what. So far, the only way I know of
doing this is with a RealProxy which parses the IMessage to call a
desired function.

I'm particularly concerned about performance, and it seems that the
TransparentProxy consumes vast amounts of resources, two orders of
magnitude, even if my RealProxy does nothing.

I made a small trivial performance suite to test different invocation
methods and interception techniques. It adds 1 to 40 as many times as
it can in 5 seconds. Results are as follows;
Direct: 66292785 counts
Direct MarshalByRefObj: 54974002
MethodInfo: 4242595
InvokeMethod: 3425953
Fake RealProxy: 581618
RealProxy: 266322

-Fake RealProxy is a InvokeMethod which calls a static test instance &
returns a pre-existing ReturnMessage. It does no thinking, just runs on
any InvokeMessage.
-Real Proxy calls RemotingServices.ExecuteMessage.
-I'm not sure if this will actually work, but i've included the sample.




Anyways, I'm wondering what alternatives are available.

I think IDynamicProperty/IDynamicMessageSink might have some similar
capabilities. I dont really understand either of these at all, and
havent found good docs either.

The other thing I was thinking of was generating wrapper assemblies.
Use reflection to parse in the entirity of a user's assembly, and emit a
wrapped version, and have the user's app read from the wrapped assembly.
I'm not sure how assemblies parallel to DLL's, but it follows the same
idea. The immediate problem I see with this is that anything within the
assembly wont be accessing the wrapped versions. If one class has an
instance of another class, it'll be the unwrapped version. Is there any
way around this? This is really my ideal solution.


Thanks
Myren

using System;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Runtime.Remoting;
using System.Collections;
using System.Timers;
using System.Reflection;

namespace Test
{
public class RunTest
{
static Timer timer;
static int time;

static public int Main (string[] args)
{
long c;

sampleTest sample1 = new sampleTest();
MethodInfo[] ms = sample1.GetType().GetMethods();
for(int i=0;i<ms.Length;i++)
{
Console.WriteLine("Name of the Method is: |"+ms.Name+"|");
}

c = 0;
startTime();
while(time > 0)
{
sample1.doTest();
c++;
}
Console.WriteLine("Raw: {0}", c);






sampleTest sample2 = new sampleTest ();
MethodInfo m = sample2.GetType().GetMethod("doTest");


c = 0;
startTime();
while(time > 0)
{
m.Invoke(sample2, new object [] {});
c++;
}
Console.WriteLine("MethodInfo: {0}", c);




sampleTest sample3= new sampleTest();
Type t = typeof(sampleTest);

c = 0;
startTime();
while(time > 0)
{
t.InvokeMember("doTest", BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Instance, null, sample3, new object[] {});
c++;
}
Console.WriteLine("InvokeMethod: {0}", c);


sampleTestMarshal sample4 = new sampleTestMarshal ();
c = 0;
startTime();
while(time > 0)
{
sample4.doTest();
c++;
}
Console.WriteLine("Marshal: {0}", c);


DumpProxy proxy5 = new DumpProxy(typeof(sampleTestMarshal));
sampleTestMarshal sample5 = (sampleTestMarshal) proxy5.GetTransparentProxy();

c = 0;
startTime();
while (time > 0)
{
sample5.doTest();
c++;
}
Console.WriteLine("DeadProxy: {0}", c);


EmptyProxy proxy6 = new EmptyProxy(typeof(sampleTestMarshal));
sampleTestMarshal sample6 = (sampleTestMarshal) proxy6.GetTransparentProxy();

c = 0;
startTime();
while (time > 0)
{
sample6.doTest();
c++;
}
Console.WriteLine("EmptyProxy: {0}", c);


ExecProxy proxy7 = new ExecProxy(typeof(sampleTestMarshal));
sampleTestMarshal sample7 = (sampleTestMarshal) proxy7.GetTransparentProxy();

c = 0;
startTime();
while (time > 0)
{
sample7.doTest();
c++;
}
Console.WriteLine("ExecProxy: {0}", c);


TcpChannel chan = new TcpChannel(42090);
ChannelServices.RegisterChannel(chan);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(sampleTestMarshal), "test", WellKnownObjectMode.Singleton);

sampleTestMarshal sample8 = (sampleTestMarshal) Activator.GetObject(
typeof(sampleTestMarshal),
"tcp://localhost:42090/test");
if (sample8 == null)
Console.WriteLine("cannot locate server");
else
{
c = 0;
startTime();
while(time > 0)
{
sample8.doTest();
c++;
}
Console.WriteLine("TcpProxy: {0}", c);
}

sampleTest sample9;
c = 0;
startTime();
while(time > 0)
{
sample9 = new sampleTest();
sample9.doTest();
c++;
}
Console.WriteLine("New Sample: {0}", c);

Console.ReadLine();
return 0;

}

static public void timeInterval(object source, ElapsedEventArgs e)
{
if(time > 0)
time--;
else
timer.Enabled = false;
}

static public void startTime()
{
time = 5;
if(timer == null)
{
timer = new System.Timers.Timer();
timer.Elapsed += new ElapsedEventHandler(timeInterval);
}
timer.Interval = 1000;
timer.Enabled = true;
}
}

public class sampleTest
{
public sampleTest() {}
public void doTest()
{
int f= 0;
for(int i = 0; i < 40; ++i)
f += i;
}
}

public class sampleTestMarshal : MarshalByRefObject
{
public sampleTestMarshal() {}
public void doTest()
{
int f= 0;
for(int i = 0; i < 40; ++i)
f += i;
}
}

public class EmptyProxy : RealProxy
{
static sampleTest st;
public EmptyProxy (Type type)
: base(type)
{
st = new sampleTest ();
}
public override IMessage Invoke(IMessage msg)
{
st.doTest();
return new ReturnMessage(null, new object[] {}, 0, (LogicalCallContext)msg.Properties["__CallContext"], (IMethodCallMessage)msg);
}
}

public class DumpProxy : RealProxy
{
static sampleTest st;
static ReturnMessage rm;

public DumpProxy (Type type)
: base(type)
{

st = new sampleTest ();
}
public override IMessage Invoke(IMessage msg)
{
st.doTest();
if(rm == null)
rm = new ReturnMessage(null, new object[] {}, 0, (LogicalCallContext)msg.Properties["__CallContext"], (IMethodCallMessage)msg);
return rm;
}
}

public class ExecProxy : RealProxy
{
static sampleTestMarshal st;

public ExecProxy (Type type)
: base(type)
{
st = new sampleTestMarshal ();
}
public override IMessage Invoke(IMessage msg)
{
IMethodCallMessage myCallMessage = (IMethodCallMessage)msg;

IMethodReturnMessage myIMethodReturnMessage =
RemotingServices.ExecuteMessage(st, myCallMessage);

return myIMethodReturnMessage;
}
}


}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top